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
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:EDIT:
Change
security="none"toaccess="IS_AUTHENTICATED_ANONYMOUSLY"and move chosen patterns to intercept-url. It should enable Spring Security’s Filter Chain and applyAnonymousAuthenticationFilteron request:assuming you want use
isAnonymous()in/,/homeand/login*.My previous solution worked, because with
security="none"checking forisAuthenticated()always yielded false, so negating it was like checking for not being loggged.