Question

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.

Was it helpful?

Solution 2

I was able to fix this issue by overriding the default filter chain (used filter chain proxy) and invoking only the required filters. Thanks LukeTaylor and Ketan for your suggestions. Please let me know if some one has the same issue. I can post my XML and other stuff.

OTHER TIPS

If your CustomAuthenticationFilter is extending AbstractPreAuthenticatedProcessingFilter, following 2 properties may give you an insight. 1. checkForPrincipalChanges 2. invalidateSessionOnPrincipalChange

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top