如何使用 Spring 安全性获取会话超时消息

Posted

技术标签:

【中文标题】如何使用 Spring 安全性获取会话超时消息【英文标题】:How to get session time out message using Spring security 【发布时间】:2016-08-11 01:16:06 【问题描述】:

我想在会话到期时获取会话超时消息。下面是我的 spring-security.xml

<http auto-config="true" use-expressions="true">
    <logout logout-success-url="/" invalidate-session="true" logout-url="/LogOut"/>
    <form-login login-page="/Login" username-parameter="Name" password-parameter="Pwd"/>
    <session-management invalid-session-url="/?timeout=true">
        <concurrency-control max-sessions="1" expired-url="/Timeout?timeout=true" />
    </session-management>
</http>

据我所知,当会话过期时使用上面的代码,它应该重定向到/?timeout=true OR /Timeout?timeout=true。注销时应该转到/。但在我的注销情况下,它也重定向到invalid-session-url,所以对于正常注销和会话超时,我总是得到超时。

请帮我区分一下。

更新

/logout 请求包含

session = request.getSession();
session.invalidate();
session = null;

【问题讨论】:

invalid-session-url 当你没有正确地使会话失效时触发,你能说明你是如何使会话失效的吗? 在您的 web.xml 中,应用程序启动时指定的默认页面是什么? 我没有指定任何东西..for "/" url 我已经加载了登录页面 【参考方案1】:

我解决了!通过编写一个过滤器,而不是依赖于 Spring-security。

如果有人有兴趣,他们可以使用以下代码:-

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.MessageFormat;

import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.springframework.web.filter.OncePerRequestFilter;

public class FilterToGetTimeOut extends OncePerRequestFilter 

    @Override
    public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException 
        try 
            if(request.getRequestURI().equals("/") || request.getRequestURI().equals("/Login/"))
                if(request.getSession().getAttribute("login") != null && (Boolean)request.getSession().getAttribute("login") == true)
                    response.sendRedirect(URL);     //After login page
                
             else if(request.getSession().getAttribute("login") == null && !request.getRequestURI().equals("/LogOut"))
                response.sendRedirect(request.getContextPath()+"/?timeout=true");   //If timeout is true send session timeout error message to JSP
            
            filterChain.doFilter(request, response);
         catch (Exception e) 
            //Log Exception

        
    

web.xml中添加这个过滤器。

    <filter>
        <filter-name>FilterToGetTimeOut </filter-name> 
        <filter-class>package.FilterToGetTimeOut </filter-class> 
    </filter>
    <filter-mapping> 
        <filter-name>FilterToGetTimeOut</filter-name> 
        <url-pattern>/*</url-pattern> 
    </filter-mapping> 

所以现在会话也失效了,我也可以处理会话超时。

【讨论】:

“登录后页面”sn-p 中的 var URL 是什么? 我不明白这条线是做什么的? response.sendRedirect(URL) 这将加载您将提到的 URL....它将重定向.....response.sendRedirect("/errorLogin"); 它将转到http:localhost:xxx/xxxx/errorLogin【参考方案2】:

我建议您使用以下方式注销:

HttpSession session= request.getSession(false);
    SecurityContextHolder.clearContext();
        if(session != null) 
            session.invalidate();
        
        for(Cookie cookie : request.getCookies()) 
            cookie.setMaxAge(0);
        

【讨论】:

我按照你的回答试过了,总是无法获得会话超时 expired-url 用于会话过期,这意味着如果应用程序检测到用户超过​​max-sessions,在这种情况下超过 1 个会话,那么 spring 将重定向到 expired-url。我的回答是确保您的注销不会转到invalid-session-url。如果你想让用户在一定时间后自动注销,你可以使用jquery。 如果我删除 session.invalidate ,实际上在注销时它也会相同 抱歉忘了一件事,如果你想使用我的答案,你需要删除spring-security.xml中的。您能说出您希望系统如何运行吗? 注销时 SpringContext 应该清除,会话应该为空,并且会话超时错误消息应该出现。【参考方案3】:

在您的情况下,当用户注销时,会话首先失效,然后会话管理将被触发。当会话管理进来,发现会话已经消失时,会话超时页面将被重定向。所以最好将logout标签的invalidate-session设置为false。

<logout logout-success-url="/" invalidate-session="false" logout-url="/LogOut"/>

【讨论】:

在提到 invalidate-session='false' 时也用于注销它的重定向到 invalidate-url【参考方案4】:

请在您的控制器中定义注销成功 url 的请求映射,并从那里重定向到主页。例如替换您的映射如下

<http auto-config="true" use-expressions="true">
<logout logout-success-url="/logoutSucess" invalidate-session="true" logout-url="/LogOut"/>
<form-login login-page="/Login" username-parameter="Name" password-parameter="Pwd"/>
<session-management invalid-session-url="/?timeout=true">
    <concurrency-control max-sessions="1" expired-url="/Timeout?timeout=true" />
</session-management>

使用@RequestMapping(value="/logoutSucess" method=RequestMethod.GET) 在控制器中定义这个/logoutSucess

【讨论】:

【参考方案5】:

我也有类似的问题,比如

    如果您使用某些用户登录,请说 zzzz 您关闭了浏览器 您再次尝试使用同一用户 zzzz 登录 登录失败并显示超出最大会话的消息

我的 spring 安全文件中的代码是:

<session-management invalid-session-url="/?timeout=true">
<concurrency-control max-sessions="1" expired-url="/logout?timeout" />

我通过在 web.xml 文件中添加会话超时条目解决了这个问题。 我将会话超时值设置为 5 分钟,构建应用程序并部署。 它工作正常。

这可能会对某人有所帮助。

谢谢, 阿图尔

【讨论】:

以上是关于如何使用 Spring 安全性获取会话超时消息的主要内容,如果未能解决你的问题,请参考以下文章

Spring消息传递+安全如何通过websockets登录?

如何使用 Spring Boot 嵌入式 tomcat 设置会话超时

如何设置弹簧安全会话超时?

会话超时后,Spring 安全性不会重定向到上次请求的页面登录

如何在 Spring Security 中关闭 HTTP 会话超时?

如何从 Spring Security 中的会话管理(超时/并发检查)中排除某些页面?