views:

17

answers:

1

Hi all,

Using Spring Security 3.1.0, I cannot seem to get the concurrent session control feature to work. When I log into my system at the same time using IE and FireFox (using my local workstation) I see my user principle in the session registry twice. I am expecting the concurrent session control to log me out or throw an exception or do something that indicates I am logged into the site more than once and it is not permitted.

For what it's worth, I could not get the concurrency control to work at all using the auto config of the HTTP namespace element, even with specifying that my site uses a custom login form. I'm wondering if that might be due to the fact that my authentication is provided via LDAP...?

Here's my security config.

<?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-3.0.xsd
           http://www.springframework.org/schema/security
           http://www.springframework.org/schema/security/spring-security-3.0.xsd"&gt;

 <http auto-config="false" use-expressions="true" entry-point-ref="authenticationProcessingFilterEntryPoint">
     <custom-filter position="CONCURRENT_SESSION_FILTER" ref="concurrencyFilter" />
     <custom-filter position="FORM_LOGIN_FILTER" ref="myAuthFilter"/>
     <session-management session-authentication-strategy-ref="sas"/>
  <intercept-url pattern="/" access="permitAll" />
  <intercept-url pattern="/css/**" access="permitAll" />
  <intercept-url pattern="/images/**" access="permitAll" />
  <intercept-url pattern="/js/**" access="permitAll" />
  <intercept-url pattern="/public/**" access="permitAll" />
  <intercept-url pattern="/home/**" access="permitAll" />
  <intercept-url pattern="/admin/user/**" access="hasRole('AUTH_MANAGE_USERS')" />
  <intercept-url pattern="/admin/group/**" access="hasRole('AUTH_MANAGE_USERS')" />
  <intercept-url pattern="/**" access="isAuthenticated()" />
  <access-denied-handler error-page="/403.html"/>
  <logout invalidate-session="true" logout-success-url="/public/home.do"/>
 </http>

    <beans:bean id="authenticationProcessingFilterEntryPoint"
          class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
        <beans:property name="loginFormUrl" value="/public/login.do"/>
        <beans:property name="forceHttps" value="false"/>
    </beans:bean>

  <beans:bean id="concurrencyFilter"
       class="org.springframework.security.web.session.ConcurrentSessionFilter">
     <beans:property name="sessionRegistry" ref="sessionRegistry" />
     <beans:property name="expiredUrl" value="/expired.html" />
   </beans:bean>

   <beans:bean id="myAuthFilter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
     <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>

 <authentication-manager alias="authenticationManager">
  <authentication-provider ref='ldapProvider' />
  <authentication-provider ref="externalUserLdapProvider"/>
 </authentication-manager>

 <beans:bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl" />

 <beans:bean id="securityContext" 
  class="org.springframework.security.core.context.SecurityContextHolder" factory-method="getContext"/>

 <beans:bean id="ldapProvider"
  class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
  <beans:constructor-arg ref="bindAuthenticator" />
  <beans:constructor-arg ref="userService" />
  <beans:property name="userDetailsContextMapper" ref="permissionedUserContextMapper" />
 </beans:bean>

 <beans:bean id="permissionedUserContextMapper"
  class="...service.impl.PermissionedUserContextMapperImpl" >
  <beans:property name="userDao" ref="userDao"/>
 </beans:bean>  

 <!-- LDAP via AD-->
 <beans:bean id="bindAuthenticator"
  class="org.springframework.security.ldap.authentication.BindAuthenticator">
  <beans:constructor-arg ref="contextSource" />
  <beans:property name="userSearch" ref="userSearch" />
 </beans:bean>

 <beans:bean id="userSearch"
  class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
  <beans:constructor-arg>
   <beans:value></beans:value>
  </beans:constructor-arg>
  <beans:constructor-arg>
   <beans:value>(sAMAccountName={0})</beans:value>
  </beans:constructor-arg>
  <beans:constructor-arg ref="contextSource" />
  <beans:property name="searchSubtree">
   <beans:value>true</beans:value>
  </beans:property>
 </beans:bean>

 <beans:bean id="contextSource"
  class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
  <beans:constructor-arg
   value="ldap://omitted" />
  <beans:property name="userDn"
   value="ommitted" />
  <beans:property name="password" value="omitted" />
 </beans:bean>

 <!--  Second LDAP Authenticator (Apache DS) -->
    <beans:bean id="externalUserLdapProvider" class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
        <beans:constructor-arg ref="externalUserBindAuthenticator"/>
  <beans:constructor-arg ref="userService" />
  <beans:property name="userDetailsContextMapper" ref="permissionedUserContextMapper" />
    </beans:bean>

 <beans:bean id="externalUserBindAuthenticator" class="org.springframework.security.ldap.authentication.BindAuthenticator">
  <beans:constructor-arg ref="externalUserContextSource" />
  <beans:property name="userDnPatterns">
   <beans:list>
    <beans:value>cn={0},ou=Users</beans:value>
   </beans:list>
  </beans:property>
 </beans:bean>

 <beans:bean id="externalUserContextSource" 
   class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
     <beans:constructor-arg value="ldap://omitted"/>
 </beans:bean>

</beans:beans>

Am I missing some property that should tell the concurrency control strategy to barf if the user logs more than 1 session? I know the same user is logging more than one session -- as I am seeing duplicate principles in the session registry.

Any/all replies are very much appreciated! Thanks in advance!

A: 

SessionRegistry uses equals()/hashCode() of UserDetails to find sessions of the same user. If you have custom UserDetails, perhaps it's not implemented.

axtavt
That was absolutely the problem. Bonehead me. Thank you so very much!
Griff