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.Simpl开发者_运维技巧eUrlAuthenticationFailureHandler">
<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?
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.
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.
精彩评论