1、在配置文件中增加 一个listen
<listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
2、FilterChainProxy 增加 ConcurrentSessionFilter
,这个Filter 要两个属性 sessionRegistry(需要SessionRegistryImpl实例expiredUrl过滤失败时跳转的url)
<http> <custom-filter position="FORM_LOGIN_FILTER" ref="loginFilter" /> <custom-filter position="CONCURRENT_SESSION_FILTER" ref="concurrentSessionFilter" /> <!-- 防止同一用户多次登录,使第二次登录失 --> <session-management session-authentication-strategy-ref="concurrentSessionControlStrategy" /> </http> <!-- Login Filter --> <beans:bean id="loginFilter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter"> <beans:property name="sessionAuthenticationStrategy" ref="concurrentSessionControlStrategy" /> <beans:property name="authenticationManager" ref="authenticationManager" /> <beans:property name="authenticationSuccessHandler" ref="loginAuthenticationSuccessHandler" /> <beans:property name="authenticationFailureHandler" ref="loginAuthenticationFailureHandler" /> </beans:bean> <beans:bean id="concurrentSessionFilter" class="org.springframework.security.web.session.ConcurrentSessionFilter"> <beans:property name="sessionRegistry" ref="sessionRegistry" /> <beans:property name="expiredUrl" value="/admin/login" /> <beans:property name="logoutHandlers"> <beans:list> <beans:ref bean="logoutHandler" /> </beans:list> </beans:property> </beans:bean> <beans:bean id="logoutHandler" class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler" /> <!-- the flowing settings for session management --> <beans:bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl" /> <beans:bean id="concurrentSessionControlStrategy" class="org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy"> <beans:constructor-arg name="sessionRegistry" ref="sessionRegistry" /> <beans:property name="maximumSessions" value="1" /> <beans:property name="migrateSessionAttributes" value="true" /> <beans:property name="exceptionIfMaximumExceeded" value="false" /> </beans:bean>
3、代码 AbstractAuthenticationProcessingFilter 在方法dofilter()根据属性 concurrentSessionControlStrategy的方法onAuthentication
在ConcurrentSessionFilter Filter 中做具体是通过还是不过的验证
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
HttpSession session = request.getSession(false);
if (session != null) {
SessionInformation info = sessionRegistry.getSessionInformation(session.getId());
if (info != null) {
if (info.isExpired()) {
// Expired - abort processing
doLogout(request, response);
String targetUrl = determineExpiredUrl(request, info);
if (targetUrl != null) {
redirectStrategy.sendRedirect(request, response, targetUrl);
return;
} else {
response.getWriter().print("This session has been expired (possibly due to multiple concurrent " +
"logins being attempted as the same user).");
response.flushBuffer();
}
return;
} else {
// Non-expired - update last request date/time
sessionRegistry.refreshLastRequest(info.getSessionId());
}
}
}
chain.doFilter(request, response);
}