Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Security, Form Login, and Concurrent Sessions

I am trying to restrict a user from signing more than once (forcing the previous session to expire).

I've checked the documentation on the subject here. I've set this up very similar to the documentation, but users are not being restricted to one session at a time. I can log in multiple times (in different browsers) with the same user and have multiple concurrent sessions going.

Here are what I believe to be the relevant bits of my security setup. I'm using custom UserDetailsService, UserDetails, and AuthenticationFilter implementations.


    <http entry-point-ref="authenticationEntryPoint">
        <!-- Make sure everyone can access the login page -->
        <intercept-url pattern="/login.do*" filters="none" />

        [...]

        <custom-filter position="CONCURRENT_SESSION_FILTER" ref="concurrencyFilter" />
        <custom-filter position="FORM_LOGIN_FILTER" ref="authenticationFilter" />

        <logout logout-url="/logout" logout-success-url="/login.do" />
    </http>

    <authentication-manager alias="authenticationManager">
        <authentication-provider user-service-ref="userDetailsService">
            <password-encoder hash="sha" />
        </authentication-provider>
    </authentication-manager>

    <beans:bean id="userDetailsService" class="[...]">
        <beans:property name="userManager" ref="userManager" />
    </beans:bean>

    <beans:bean id="authenticationFilter" class="[...]">
        <beans:property name="authenticationManager" ref="authenticationManager" />
        <beans:property name="eventPublisher">
            <beans:bean
                class="org.springframework.security.authentication.DefaultAuthenticationEventPublisher" />
        </beans:property>
        <beans:property name="filterProcessesUrl" value="/security_check" />
        <beans:property name="authenticationFailureHandler">
            <beans:bean
                class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
                <beans:property name="defaultFailureUrl" value="/login.do?login_error=true" />
            </beans:bean>
        </beans:property>
        <beans:property name="sessionAuthenticationStrategy"
            ref="sessionAuthenticationStrategy" />
    </beans:bean>

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

    <beans:bean id="concurrencyFilter"
        class="org.springframework.security.web.session.ConcurrentSessionFilter">
        <beans:property name="sessionRegistry" ref="sessionRegistry" />
        <beans:property name="expiredUrl" value="/login.do?login_error=true!" />
    </beans:bean>

    <beans:bean id="sessionAuthenticationStrategy"
        class="org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy">
        <beans:constructor-arg name="sessionRegistry"
            ref="sessionRegistry" />
        <beans:property name="maximumSessions" value="1" />
    </beans:bean>

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

I've also registered org.springframework.security.web.session.HttpSessionEventPublisher as a listener in my web.xml file.

As far as I can tell, I've configured this according to the documentation. I can't tell why this isn't working. Could it have something to do with the fact that I'm using a form-based login? Or my custom implementations mentioned above?

like image 586
ajduff574 Avatar asked Dec 21 '22 23:12

ajduff574


2 Answers

I figured it out. If you reimplement UserDetails, you must provide a hashCode() method for SessionRegistryImpl to use. This is not mentioned in the documentation.

like image 120
ajduff574 Avatar answered Dec 28 '22 05:12

ajduff574


I know this has already been answered but there is a much simpler solution which doesn't require configuring specific filters. You can add to the http tag the following XML to configure your sessions:

<session-management invalid-session-url="/login">
  <concurrency-control max-sessions="1" expired-url="/login" />
</session-management>

The rest of the form based login configuration is also overly complicated. I wrote a post here http://codehustler.org/blog/spring-security-form-login-tutorial/ which shows how to configure the form-login properly.

like image 25
Alessandro Giannone Avatar answered Dec 28 '22 07:12

Alessandro Giannone