超过此主体的最大会话时的Spring安全重定向

时间:2013-02-21 20:22:22

标签: java spring spring-security

因此用户登录 - > 关闭浏览器 - > 再次打开浏览器 - > 错误:

HTTP Status 401 - Authentication Failed: Maximum sessions of 1 for this principal exceeded

我需要的是捕获会话无效的事件,删除该用户的所有会话并重定向到正常登录页面

spring security config:

        <http auto-config="true" use-expressions="true">
                <session-management session-fixation-protection="migrateSession">
                    <concurrency-control max-sessions="1" error-if-maximum-exceeded="true"/>
                </session-management>   
                <intercept-url pattern="/login" access="hasRole('ROLE_ANONYMOUS')" requires-channel="any"/> 

    <!--<custom-filter after="CONCURRENT_SESSION_FILTER" ref="sessionExpiration" /> -->
    <!-- .... -->

        </http>

<beans:bean id="sessionExpiration" class="com.test.security.SessionExpirationFilter">
    <beans:property name="expiredUrl">
            <beans:value>/login</beans:value>
        </beans:property>
 </beans:bean>

我试图实现一些过滤器,但它总是显示会话为空:

public class SessionExpirationFilter implements Filter, InitializingBean {
    private String expiredUrl;

    public void destroy() {
    }

    public void doFilter(ServletRequest request, ServletResponse response,
        FilterChain chain) throws IOException, ServletException {

        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;

        String path = httpRequest.getServletPath();
        HttpSession session = httpRequest.getSession(false);

        System.out.println(session);
        if (session == null && !httpRequest.isRequestedSessionIdValid()) {              
            SecurityContextHolder.getContext().setAuthentication(null);
            String targetUrl = httpRequest.getContextPath()
                    + expiredUrl;
            httpResponse.sendRedirect(httpResponse.encodeRedirectURL(targetUrl));
            return;
        }
        chain.doFilter(request, response);
    }

    public void setExpiredUrl(String expiredUrl) {
        this.expiredUrl = expiredUrl;
    }
}

4 个答案:

答案 0 :(得分:6)

根据我的理解,如果用户的会话超过“max-sessions”,您希望使之前的会话无效。将属性'error-if-maximum-exceeded'设置为false。 Spring安全性会自动使上一个会话无效。

如果你想尝试不同的事情,

  1. 扩展ConcurrentSessionControlStrategy类,并覆盖 'allowableSessionsExceeded'方法。
  2. 将上述bean引用指定为'session-management'的'session-authentication-strategy-ref'属性值

答案 1 :(得分:2)

设置error-if-maximum-exceeded="false"将允许第二个会话并使第一个会话无效max-sessions="1"

如果您有max-sessions="2",那么它也会允许Nth会话并使所有N-2次会话无效

<session-management session-fixation-protection="migrateSession">
    <concurrency-control max-sessions="1" error-if-maximum-exceeded="false"/>
</session-management> 

设置error-if-maximum-exceeded="true"NOT允许第二个会话,并使第二个会话无效为max-sessions="1"

如果您有max-sessions="2",那么它将不允许2+个会话并且无效。

答案 2 :(得分:0)

基于以上答案

  

Spring安全性会自动使上一个会话无效

如果要在登录页面上重定向用户,可以添加

<session-management invalid-session-url="/login.html">
    ...
</session-management>

由于上一个会话已经无效。


我在上面的评论中也已经读到,当您尝试再次登录时,您可能希望保留上一个会话。但这仍然打败了您的第一个问题。

您在谈论7. Session Fixation Protection with Spring Security

  

该框架提供了针对典型会话修复的保护   通过配置现有会话发生什么情况来进行攻击   用户尝试再次进行身份验证:

     

<session-management session-fixation-protection="migrateSession">

     

相应的Java配置:

     

http.sessionManagement().sessionFixation().migrateSession()

     

默认情况下,Spring Security启用了此保护   (“ migrateSession”)–进行身份验证后,将创建一个新的HTTP会话,   旧会话无效,旧会话的属性为   复制过来。

     

如果这不是所需的行为,则可以使用其他两个选项:

     

设置“none”时,原始会话不会无效

     

设置“newSession”时,将创建一个干净的会话,而没有任何   从旧会话复制过来的属性

答案 3 :(得分:-1)

&#13;
&#13;
<session-management session-authentication-strategy-ref="sas"/>
<beans:bean id="sas" class="org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy">
        <beans:property name="maximumSessions" value="1"/>
        <beans:property name="exceptionIfMaximumExceeded" value="true"/>
        <beans:constructor-arg name="sessionRegistry" ref="sessionRegistry"/>
    </beans:bean>
    <beans:bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl"/>
&#13;
&#13;
&#13;