I have been using Spring Security 2.x for some time now, but recently I switched to 3.x. I always use my own implementation of UserDetails interface and authentication against DB.
Everything works fine (logging in, logging out, url filters, seeing username of authorized user, etc.).
The only thing left to do was to display "Please login" message when user is not authorized. I tried few approaches:
<sec:authorize access="not isAnonymous()">
or
<sec:authorize access="hasRole('ROLE_ANONYMOUS')">
etc.
None of them worked. Finally I added <sec:authentication property="principal.authorities" /> to my home page output to debug what roles user really has. This is what I see:
Logged user - [ROLE_USER, ROLE_ADMIN]
Unathorized user - `` <- empty String
It looks like I somehow lost the default ROLE_ANONYMOUS authority, which was always added by Spring, if I recall correctly. Was that recently dropped or something? Perhaps I have to take care of this anonymous access in some other manner?
Relevant part of security context:
<beans:beans
xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<!-- UNPROTECTED RESOURCES -->
<http pattern="/" security="none"/>
<http pattern="/favicon.ico" security="none"/>
<http pattern="/home" security="none"/>
<http pattern="/login*" security="none"/>
<http pattern="/resources/**" security="none"/>
<!-- PROTECTED RESOURCES -->
<http auto-config='true' use-expressions="true">
<intercept-url pattern="/**" access="hasRole('ROLE_USER')"/>
<intercept-url pattern="/admin/**" access="hasRole('ROLE_USER,ROLE_ADMIN')"/>
<form-login login-page="/login" default-target-url="/dashboard" authentication-failure-url="/login?login_error=true"/>
<logout logout-url="/logout"/>
</http>
<beans:bean id="userAccountsAuthenticationProvider" class="pl.xxx.utils.UserAccountsAuthenticationProvider" />
<beans:bean id="saltSource" class="org.springframework.security.authentication.dao.ReflectionSaltSource">
<beans:property name="userPropertyToUse" value="salt" />
</beans:bean>
<authentication-manager>
<authentication-provider user-service-ref="userAccountsAuthenticationProvider">
<password-encoder ref="standardPasswordEncoder"/>
</authentication-provider>
</authentication-manager>
</beans:beans>
Anonymous Authentication can be configured in few different ways - do you use <http auto-config="true">, <anonymous> tag or define beans by yourself as custom filter? It'll be easier if you posted your security-context.xml.
Anyway, you want to display "Please login", so I assume you really wanted
<sec:authorize access="isAnonymous()">Please login</sec:authorize>
without "not" (by the way I can't find if "not" is a valid part of expression in this context).
Another way is to use isAuthenticated() instead, negate it in EL and see if it works in your case:
<sec:authorize access="isAuthenticated()" var="isAuthenticated" />
<c:if test="${not isAuthenticated}">
<!-- do stuff -->
</c:if>
EDIT:
Change security="none" to access="IS_AUTHENTICATED_ANONYMOUSLY" and move chosen patterns to intercept-url. It should enable Spring Security's Filter Chain and apply AnonymousAuthenticationFilter on request:
<!-- UNPROTECTED RESOURCES -->
<http pattern="/favicon.ico" security="none"/>
<http pattern="/resources/**" security="none"/>
<!-- PROTECTED RESOURCES -->
<http auto-config='true' use-expressions="true">
<intercept-url pattern="/" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<intercept-url pattern="/home" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<intercept-url pattern="/login*" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<intercept-url pattern="/**" access="hasRole('ROLE_USER')"/>
<intercept-url pattern="/admin/**" access="hasRole('ROLE_USER,ROLE_ADMIN')"/>
<form-login login-page="/login" default-target-url="/dashboard" authentication-failure-url="/login?login_error=true"/>
<logout logout-url="/logout"/>
</http>
assuming you want use isAnonymous() in /, /home and /login*.
My previous solution worked, because with security="none" checking for isAuthenticated() always yielded false, so negating it was like checking for not being loggged.
Related
Code was working fine now have replaced the below line in security.xml to provide role based security, but getting access denied http status-403
Replaced
<intercept-url pattern="/inputcreate*" access="isAuthenticated()" />
with
<intercept-url pattern="/inputcreate*" access="hasAnyRole('admin','user')" />
spring-security.xml
<http use-expressions="true" auto-config="true">
<!-- <intercept-url pattern="/inputcreate*" access="isAuthenticated()" /> -->
<intercept-url pattern="/inputcreate*" access="hasAnyRole('admin','user')" />
<form-login login-page="/login.html" default-target-url="/inputcreate.html"
authentication-failure-url="/login.html" username-parameter="j_username"
password-parameter="j_password" login-processing-url="/j_spring_security_check" />
<logout logout-url="/j_spring_security_logout"
logout-success-url="/index.html" />
</http>
just Replaced
<intercept-url pattern="/inputcreate*" access="hasAnyRole('admin','user')" />
with
<intercept-url pattern="/inputcreate*" access="hasAnyRole('ROLE_ADMIN','ROLE_USER')" />
After googling 3-4 hour, made this above change
This worked for me!!!!
In the Spring documentation it has been given here, to prefix role
public void setRolePrefix(String rolePrefix)
Allows a default role prefix to be specified. If this is set to a non-empty value, then it is automatically prepended to any roles read in from the db.
This may for example be used to add the ROLE_ prefix expected to exist in role names (by default) by some other Spring Security classes, in the case that the prefix is not already present in the db.
Parameters:
rolePrefix - the new prefix
I am pretty new in Spring Security and I have the following problem.
I have this controller method that handle request toward the /riepilogoCentrale resource
#RequestMapping(value = "/riepilogoCentrale", method = RequestMethod.GET)
public String riepilogoUtenteCentrale(HttpServletRequest request, Model model, Locale locale) {
System.out.println("INTO riepilogoUtenteCentrale()");
return "centrale/riepilogoCentrale";
}
My problem is that this resource (so the related rendered page) have to be accessible to everyone (also the not logged user) and as it is actually configured Spring Security if I try to access to this resource as visitor (not logged user) Spring redirects me to the log in page.
This is my Spring Security configuration file (named spring-security.xml):
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-4.0.xsd">
<http pattern="/resources/**" security="none"/>
<http auto-config="true" use-expressions="true" authentication-manager-ref="authenticationManager">
<intercept-url pattern="/login" access="permitAll" />
<intercept-url pattern="/registrati" access="permitAll" />
<intercept-url pattern="/salvaRegistrazione" access="permitAll" />
<intercept-url pattern="/captcha.html" access="permitAll" />
<intercept-url pattern="/**" access="isAuthenticated()" />
<logout logout-success-url="/login" logout-url="/logout" />
<form-login login-page="/login"
authentication-failure-url="/login?error=true"
default-target-url="/"
username-parameter="nomeUtente"
password-parameter="password"
login-processing-url="/j_spring_security_check"/>
<csrf disabled="true"/>
</http>
<authentication-manager id="authenticationManager" >
<authentication-provider>
<jdbc-user-service data-source-ref="datasource"
users-by-username-query="select des_usr_par, des_psw_par,true from TID001_ANAGPARTECIPA where des_usr_par =?"
authorities-by-username-query="select des_usr_par, prg_par from TID001_ANAGPARTECIPA where des_usr_par = ? "/>
</authentication-provider>
</authentication-manager>
</beans:beans>
So, how can I exclude the /riepilogoCentrale from the Spring Security management and make it accessible also to the not logged users ?
You're already doing this for some of your resources; for example:
<intercept-url pattern="/salvaRegistrazione" access="permitAll" />
I would imagine that you'd add another intercept-url value including /riepilogoCentrale as the pattern, and implement other business logic inside of your controller based on whether or not the user is authenticated.
You are already excluding some resources.
<http pattern="/resources/**" security="none"/>
Just add the same entry with your riepilogoCentrale-resource.
I created a spring mvc application with spring security. I tried to set authentication for all url with spring security.
Springsecurity.xml
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/**" access="hasRole('ROLE_ADMIN')" />
<!-- access denied page -->
<access-denied-handler error-page="/403" />
<form-login
login-page="/login"
default-target-url="/welcome"
authentication-failure-url="/login?error"
username-parameter="username"
password-parameter="password" />
<logout logout-success-url="/login?logout" />
<!-- enable csrf protection -->
<csrf />
</http>
<authentication-manager>
<authentication-provider user-service-ref="userDetailsService" >
<password-encoder hash="bcrypt" />
</authentication-provider>
</authentication-manager>
When I giving intercept-url to /** the page doesnot loading. It makes a timeout.
But when giving intercept-url to /admin it works perfectly. Why this happens?
Your intercept pattern for all request is OK, but you need to include an exception for your login page, try adding
<http security="none" pattern="/login"/>
UPDATE with respect to the comment
The approach above completely switches off Spring security for the given URL. As you're using CSFR, it means that spring security filter should attend to this URL as well, but not for the sake of the authentication, rather for the sake of including the unpredictable token that can secure from session fixation attacks. In any case, here's a way to process the URL with spring security, without prompting for authentication. Instead of using the above, use the following
<intercept-url pattern="/login" access="isAnonymous()"/>
inside the
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/login" access="isAnonymous()"/>
<intercept-url pattern="/**" access="hasRole('ROLE_ADMIN')" />
...
I have this spring security configuration:
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/home.jsp" access="permitAll" />
<intercept-url pattern="/loginFailed" access="permitAll" />
<intercept-url pattern="/logOut" access="permitAll" />
<intercept-url pattern="/*" access="isAuthenticated()" />
<form-login login-page="/home.jsp" default-target-url="/index"
authentication-failure-url="/loginFailed" />
<logout logout-success-url="/logOut"/>
</http>
<authentication-manager>
<authentication-provider>
<user-service>
<user name="N_a" password="12" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
If I type url, that need access="isAuthenticated() I redirect to home.jsp.
I want to see 403 error.
How to change it ?
You are using a form-based login and as such, when not authenticated, you will be prompted with the login-page. This is what you have configured and this is how, by default, Spring Security works.
If you want to override this you need to explicitly configure an AuthenticationEntryPoint to be precise the Http403ForbiddenEntryPoint. This basically always gives a 403 if someone isn't authenticated or doesn't have access. This disables the ability to be prompted with a login-form to give a user the change to login after all.
<beans:bean id="entryPoint" class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint" />
<http auto-config="true" use-expressions="true" entry-point-ref="entryPoint">
<!-- Your other elements here -->
</http>
use access-denied-handler tag in http tag.
http://www.mkyong.com/spring-security/customize-http-403-access-denied-page-in-spring-security/
or use access-denied-page property.
<http auto-config="true" access-denied-page="/403"></http>
I have project secured via Spring security. I need to determine whether the user, who just accessed to JSP is already logged in. I've read some articles, posts here and documentation and tried to implement it with this code:
<sec:authorize ifAnyGranted="ROLE_ANONYMOUS">
USER NOT LOGGED IN
<td>Login</td>
</sec:authorize>
<sec:authorize ifNotGranted="ROLE_ANONYMOUS">
USER LOGGED IN
<td>Logout</td>
</sec:authorize>
Nevertheless I always get "USER LOGGED IN" and I can't realize why.. This is my security context
<beans xmlns:security="http://www.springframework.org/schema/security"
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<security:http pattern="/resources/**" security="none"/>
<security:http pattern="/login*" security="none" auto-config="true"/>
<security:http pattern="/denied" security="none"/>
<security:http auto-config="true" access-denied-page="/denied" servlet-api-provision="false">
<security:intercept-url pattern="/login*" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<security:intercept-url pattern="/edit/**" access="ROLE_EDIT"/>
<security:intercept-url pattern="/admin/**" access="ROLE_ADMIN"/>
<security:intercept-url pattern="/**" access="ROLE_USER"/>
<security:form-login login-page="/login" authentication-failure-url="/denied"
default-target-url="/"/>
<security:logout logout-success-url="/login" />
</security:http>
<security:authentication-manager>
<security:authentication-provider>
<security:user-service>
<security:user name="adam" password="adampassword" authorities="ROLE_USER"/>
<security:user name="jane" password="janepassword" authorities="ROLE_USER, ROLE_ADMIN"/>
<security:user name="sue" password="suepassword" authorities="ROLE_USER, ROLE_EDIT"/>
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
</beans>
I'd appreciate any help :)
If a page is accesible to anyone, as set in your secruity context, you can conditionally display content like so :
<sec:authorize var="loggedIn" access="isAuthenticated()"/>
and using fairly standard jstl you can then :
<c:choose>
<c:when test="${loggedIn}">
<td>Logout</td>
A tad of googling tells me ifnotgranted is deprecated