I'm new to Spring Security. I have a requirement to do a URL based authentication wherein a user needs to be authenticated based on a unique reference that will be sent every time as a parameter in the URL. I'll pass on this reference to a webservice, get the required data and then authenticate the user (and set the roles). The Authentication & Authorization part is working fine.
However, when i try to access the application again (now with a different reference in the URL), it says "SecurityContextHolder not populated with anonymous token, as it already contained ..." and it showed the details of the previous request. I've tried clearing the security context using SecurityContextHolder.getContext().setAuthentication(null) and SecurityContextHolder.clearContext().
After this, i was able to access the application multiple times. However, if i try to access the application simultaneously from my colleagues machine, i get a blank page. Upon checking the logs, i see a message "SecurityContextHolder not populated with anonymous token ...". I've also tried setting up the sessions but I'm clueless as to where I'm losing the track.
Below is my web.xml (only the spring security part):
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<listener>
<listener-class>
org.springframework.security.web.session.HttpSessionEventPublisher
</listener-class>
</listener>
<session-config>
<session-timeout>30</session-timeout>
</session-config>
spring-security.xml:
<http use-expressions="true" auto-config="false" entry-point-
ref="http403ForbiddenEntryPoint">
<intercept-url pattern="/paymentPortalInternal.*" access="hasRole('Internal')"/>
<intercept-url pattern="/paymentPortalExternal.*" access="hasRole('External')"/>
<custom-filter position="PRE_AUTH_FILTER" ref="customAuthenticationFilter"/>
<custom-filter position="CONCURRENT_SESSION_FILTER" ref="concurrencyFilter" />
<session-management session-authentication-strategy-ref="sas"/>
</http>
<beans:bean id="concurrencyFilter"
class="org.springframework.security.web.session.ConcurrentSessionFilter">
<beans:property name="sessionRegistry" ref="sessionRegistry" />
<beans:property name="expiredUrl" value="/session-expired.htm" />
</beans:bean>
<beans:bean id="http403ForbiddenEntryPoint"
class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint"/>
<beans:bean id="customAuthenticationFilter"
class="com.xxx.xxx.xxxxx.security.CustomAuthenticationFilter">
<beans:property name="sessionAuthenticationStrategy" ref="sas" />
<beans:property name="authenticationManager" ref="authenticationManager" />
</beans:bean>
<beans:bean id="sas"
class="org.springframework.security.web.authentication.session.
ConcurrentSessionControlStrategy">
<beans:constructor-arg name="sessionRegistry" ref="sessionRegistry" />
<beans:property name="maximumSessions" value="1" />
<beans:property name="exceptionIfMaximumExceeded" value="true" />
</beans:bean>
<beans:bean id="sessionRegistry"
class="org.springframework.security.core.session.SessionRegistryImpl" />
<authentication-manager alias="authenticationManager">
<authentication-provider ref="preauthAuthProvider" />
</authentication-manager>
<beans:bean id="preauthAuthProvider"
class="org.springframework.security.web.authentication.preauth.
PreAuthenticatedAuthenticationProvider">
<beans:property name="preAuthenticatedUserDetailsService">
<beans:bean class="com.XXX.XXXX.XXX.UserServiceImpl" />
</beans:property>
</beans:bean>
Please let me know if I need to provide more information.
EDIT: Adding Logs.
For the first Request:
2013-02-07 17:27:38,834 DEBUG [http-8081-2][org.springframework.security.web.context.HttpSessionSecurityContextRepository.readSecurityContextFromSession(127)] - No HttpSession currently exists 2013-02-07 17:27:38,834 DEBUG [http-8081-2][org.springframework.security.web.context.HttpSessionSecurityContextRepository.loadContext(85)] - No SecurityContext was available from the HttpSession: null. A new one will be created.
For the second request(Please note that the details in the security context are those of the first request):
2013-02-07 17:27:54,272 DEBUG [http-8081-2][org.springframework.security.web.context.HttpSessionSecurityContextRepository.readSecurityContextFromSession(158)] - Obtained a valid SecurityContext from SPRING_SECURITY_CONTEXT: 'org.springframework.security.core.context.SecurityContextImpl@1017293c: Authentication: org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken@1017293c: Principal: org.springframework.security.core.userdetails.User@35cd3811: Username: Internal@5581e6e1-7e61-41bb-9257-b3c1acb96519; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: Internal; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@ffffc434: RemoteIpAddress: 10.188.182.107; SessionId: null; Granted Authorities: Internal'
My understanding is that security context holder stores the details of all the users. But in this case, I'm not able to launch the application from a different tab/browser.
If your CustomAuthenticationFilter is extending AbstractPreAuthenticatedProcessingFilter
, following 2 properties may give you an insight.
1. checkForPrincipalChanges
2. invalidateSessionOnPrincipalChange