有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

会话过期后java自动注销

我们的应用程序在30分钟后注销,并被重定向到登录页面,我在web中指定会话超时。xml和使用requestProcessor进行重定向。我想向用户显示一条消息,说明您的会话在会话过期后已过期,我如何才能做到这一点。自动注销? 我想在“会话超时,请重新登录”页面上提示错误消息。那么如何检测会话超时?会自动触发任何方法吗


共 (5) 个答案

  1. # 1 楼答案

    在JSP中包含一个javascript实用程序函数,并每31分钟ping一次服务器。 上述实用程序函数应该在内部使用setTimeout()JS函数

    setTimeout ( "checkServerSession()",  /* intervalInMilliSeconds */ 31000);
    

    注意

    checkServerSession()

    是一个常规的JS函数,可以触发HTTP请求。如果请求成功,则会话存在,否则向用户显示提示

  2. # 2 楼答案

    无论是简单的servlet、spring mvc还是spring security,如果没有完美的客户端逻辑,自动注销都是不可能的
    考虑到申请将有两种类型的请求

    • AJAX和
    • 表单提交/页面重新加载

    自动注销需要非常精确的逻辑。用以下内容展示我的自动功能实现

    优势


    1.不使用额外的呼叫/请求来实现此目的。考虑到超过10k的活跃用户和额外呼叫对性能的影响,以实现自动注销
    2.使用标签的单线配置
    3.即使用户打开多个选项卡或多个窗口,也能完美工作
    4.它会在会话失效30秒前通知您,因此如果您已填写表单但未提交,您可以保持会话活动(通过单击扩展会话)。因此,用户不太可能丢失未保存的数据。

    用法


    1。在所需的JSP页面中包含自动注销脚本,如下所示

        ....
        </body>
        <jsp:include page="../template/autologout-script.jsp"></jsp:include>
    </html>
    

    2。创建一个JSP页面,自动编译脚本。jsp并添加以下代码 注:无需编辑/配置

    <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
    
    <script>
    $(document).ready(function()
    {
        var timeOutTimeInSeconds = ${ timeOutTimeInSeconds }; 
        var showTimerTimeInSeconds= ${ showTimerTimeInSeconds };
    
        var sessionCheckIntervalId = setInterval(redirectToLoginPage, timeOutTimeInSeconds * 1000);
        var timerDisplayIntervalId = setInterval(showTimer, (timeOutTimeInSeconds - showTimerTimeInSeconds) * 1000);
        var badgeTimerId;
        window.localStorage.setItem("AjaxRequestFired", new Date());
    
        function redirectToLoginPage(){
            //location.href =  '<c:url value="/" />'+'${loginPageUrl}';
            window.location.reload();
        }
    
        $(document).ajaxComplete(function () {
            resetTimer();
        });
    
        $(window).bind('storage', function (e) {
             if(e.originalEvent.key == "AjaxRequestFired"){
                 console.log("Request sent from another tab, hence resetting timer")
                 resetTimer();
             }
        });
    
        function resetTimer()
        {
            showTimerTimeInSeconds= ${ showTimerTimeInSeconds };
    
            console.log("timeOutTimeInSeconds : "+timeOutTimeInSeconds)
            window.localStorage.setItem("AjaxRequestFired", new Date());
    
            window.clearInterval(sessionCheckIntervalId);
            sessionCheckIntervalId = setInterval(redirectToLoginPage, timeOutTimeInSeconds * 1000);
    
            window.clearInterval(timerDisplayIntervalId);
            timerDisplayIntervalId = setInterval(showTimer, (timeOutTimeInSeconds - showTimerTimeInSeconds) * 1000);
    
            hideTimer();
        }
    
        function showTimer()
        {
            $('#sessionTimeRemaining').show();
            $('#sessionTimeRemainingBadge').html(showTimerTimeInSeconds--);
            window.clearInterval(timerDisplayIntervalId);
            badgeTimerId = setInterval(function(){
                $('#sessionTimeRemainingBadge').html(showTimerTimeInSeconds--);
            }, 1000);
        }
    
        function hideTimer()
        {
            window.clearInterval(badgeTimerId);
            $('#sessionTimeRemaining').hide();
        }
    });
    </script>
    

    3。将会话属性配置为配置超时设置 注意:在创建会话后配置此选项。您可以实现HttpSessionListener sessionCreated方法,并根据需要设置以下配置

    session.setMaxInactiveInterval(300);
    
    session.setAttribute("timeOutTimeInSeconds", 300);
    session.setAttribute("showTimerTimeInSeconds", 30);
    
    

    4。添加下面显示计时器的html
    注意:如果你擅长CSS,可以将其移动到自动脚本模板页面。因此,您可以避免在每一页中都添加此选项
    包括引导或添加自定义css

    <span class="badge badge-primary" title="click to keep session alive" id="sessionTimeRemaining" 
        onclick="ajaxSessionRefresh()" style="display:none;">
        <i class="badge badge-danger" id="sessionTimeRemainingBadge" style="float:left">30</i>
         &nbsp; 
         <small>Refresh</small>
         <i class="glyphicon glyphicon-refresh"></i>
    </span>
    

    enter image description here

    这就是一个简单的自动注销实现。 您可以从我的github存储库下载工作示例
    Autologout using simple servlet example
    Autologout using spring-security java configuration example
    Autologout using spring-security xml configuration example

    逻辑解释


    案例1:页面加载
    这里的逻辑很简单,页面加载设置计时器的间隔等于maxInactiveInterval。超时后重定向到登录页面
    案例2:跟踪AJAX调用
    现在考虑AJAX请求,您可以使用。ajaxStart()或。ajaxComplete()回调jquery,以便在触发任何ajax请求时可以重置间隔
    案例3:跟踪多选项卡/窗口活动
    Intertab通信是为了同步每个选项卡的状态。更改事件时使用了localStorage

    需要的限制/改进
    1.如果允许的最大会话数为1,如果会话来自另一个系统,AJAX请求将失败。它需要处理重定向到登录页面
    2.使用ajaxStart()而不是ajaxComplete()在服务器和浏览器之间精确同步空闲时间值

    要求
    1.Jquery

    比较当前实施的替代方案


    1.在http响应中设置刷新头(不适用于AJAX请求)
    response.setHeader("Refresh", "60; URL=login.jsp");
    
    1. 在HTML中设置元刷新标记(不适用于AJAX请求)
    <meta http-equiv="refresh" content="60; url=login.jsp">
    
    1. 配置活动检查器 通过重复的AJAX请求保持会话活动。跟踪空闲时间,并在超时后发出注销请求
      毫无疑问,这是一个逻辑简单的好方法。但我只想记录下我的观察结果。
      • 性能影响如果每分钟发出两个请求以保持会话活动和50k活跃用户。每分钟10万个请求
      • 选项卡间通信如果两个选项卡打开,一个选项卡正在接收活动,而另一个选项卡未接收活动,则该选项卡会发出注销请求并使会话无效,即使其他选项卡中存在活动。(但可以处理)
      • 强制注销方法这是一种客户机主导服务器使会话无效的方法
  3. # 3 楼答案

    当用户每分钟点击一次“活动”时,用户会检查服务器是否处于活动状态,如果用户每分钟点击一次“活动”,则会检查服务器是否处于活动状态。如果30分钟内没有活动(或者服务器端设置了默认会话超时),则执行重定向

    下面是一个启动示例,它几乎没有jQuery的帮助,可以绑定click和keypress事件并触发ajax请求

    <script src="http://code.jquery.com/jquery-latest.min.js"></script>
    <script>
        $(document).ready(function() {
            $.active = false;
            $('body').bind('click keypress', function() { $.active = true; });
            checkActivity(1800000, 60000, 0); // timeout = 30 minutes, interval = 1 minute.
        });
    
        function checkActivity(timeout, interval, elapsed) {
            if ($.active) {
                elapsed = 0;
                $.active = false;
                $.get('heartbeat');
            }
            if (elapsed < timeout) {
                elapsed += interval;
                setTimeout(function() {
                    checkActivity(timeout, interval, elapsed);
                }, interval);
            } else {
                window.location = 'http://example.com/expired'; // Redirect to "session expired" page.
            }
        }
    </script>
    

    创建一个Servlet监听/heartbeat并基本上只执行以下操作:

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) {
        request.getSession();
    }
    

    让会议继续下去

    当您将登录的用户存储在会话中时,每当会话过期时,该用户将“自动”注销。所以你不需要手动注销用户

  4. # 4 楼答案

    如果使用的是servlet会话,可以使用isNew()方法检查jsp/servlet返回的会话是否是新的。如果是,则表示用户的会话已过期,您可以显示相关消息