在会话超时之前警告用户

Posted

技术标签:

【中文标题】在会话超时之前警告用户【英文标题】:Warn the user before session timeout 【发布时间】:2014-07-18 19:02:47 【问题描述】:

我在Spring MVCJSP 中实现了一个 Web 应用程序。 默认会话超时在web.xml 中定义为 30 分钟。

如果用户空闲 25 分钟,我需要向用户显示一个弹出窗口,其中包含 Your session is going to be end by 5 min, Please click OK to continue 的消息。

我们是否可以使用javascriptjquery 或任何其他方法来实现这一目标?

请提出建议。

【问题讨论】:

你可以使用 websockets @GovindSinghNagarkoti 如何使用 websockets?我找不到任何示例 【参考方案1】:

您可以使用以下插件 - Jtimeout jquery plugin 完美运行,也可配置。文档很清楚

【讨论】:

请在您的回答中提供更详细的解释。强烈鼓励答案将其解决方案完全放在帖子本身中。这意味着不仅仅包含指向某些外部资源的链接。如果您包含的链接中断,您的答案将变得比无用更糟糕。也许写一个使用您链接的插件的小示例,或者至少突出显示您认为可以解决提问者问题的特定插件方法。【参考方案2】:

为了在前端通知用户超时,您需要从后端传递此信息。为此,我使用https://www.javaworld.com/article/2073234/tracking-session-expiration-in-browser.html 中的信息作为基线。

在控制器的每个响应方法中,您需要包含包含会话超时时间以及当前服务器时间的 cookie。由于听起来您已经在 web.xml 中设置了会话超时,因此您可以将 cookie 添加到您的响应中,类似于:

@RequestMapping(value="/example", method = RequestMethod.GET, produces = "application/json")
@ResponseBody
public ResponseEntity<Object> getExample(HttpServletRequest servletRequest, HttpServletResponse servletResponse) 
     addTimeoutCookies(servletRequest, servletResponse);

     //Do actual actions

     return new ResponseEntity<Object>(HttpStatus.OK)


private void addTimeoutCookies(HttpServletRequest servletRequest, HttpServletResponse servletResponse) 

    long currTime = System.currentTimeMillis();
    long expiryTime = currTime + servletRequest.getSession().getMaxInactiveInterval() * 1000;

    Cookie serverTimeCookie = new Cookie("serverTime", "" + currTime);
    serverTimeCookie.setPath("/");
    servletResponse.addCookie(serverTimeCookie);

    Cookie expiryCookie = new Cookie("sessionExpiry", "" + expiryTime);
    expiryCookie.setPath("/");
    servletResponse.addCookie(expiryCookie);

然后,在前端,您需要检索这些 cookie 的值并将它们与客户端当前时间进行比较,以确定何时通知用户即将到来的会话超时。这是一个简单的代码块,基于此处的其他答案和链接中的文章:

var currTimeCookieName = 'serverTime';
var expireTimeCookieName = 'sessionExpiry';
var offset;
var warningTime = 5 * 60 * 1000;
var timeoutWarningMessage = 'Your session is going to be end by 5 min, Please click OK to continue';

function getCookie(name)

    var name = name + "=";
    var ca = document.cookie.split(';');
    for(var i=0; i<ca.length; i++)
    
        var c = ca[i].trim();
        if (c.indexOf(name)==0) return c.substring(name.length,c.length);
    
    return "";


var serverTime = getCookie(currTimeCookieName);
serverTime = serverTime==null ? null : Math.abs(serverTime);
var offset = (new Date()).getTime() - serverTime;

function getTimeToWarning() 
    var expireTime = getCookie(expireTimeCookieName);
    return expireTime + offset - currTime - warningTime;


function checkForTimeout() 
    var timeUntilWarning = getTimeToWarning();

    setTimeout(function()
        if (getTimeToWarning() > 0) 
            checkForTimeout();
         else 

            if(confirm(timeoutWarningMessage)) 
                //TODO do a backend call or other action to extend the session here

                setTimeout(function() 
                    checkForTimeout();
                , 1 * 60 * 1000);
            
        
    , timeUntilWarning);


checkForTimeout();

【讨论】:

【参考方案3】:

你可以像下面这样使用:我在像 header.jsp 这样的 jsp 页面中使用它。这对我来说可以。我正在使用 spring、jsp 和 jquery。

javascript:

<code>
<script type="text/javascript">
    //var recall = true;
    function loadDialog()  
            var sessionAlive = $pageContext.session.maxInactiveInterval;          
            var notifyBefore = 30; // Give client 15 seconds to choose.
            setTimeout(function()        
                $(function() 
                    $( "#dialog" ).dialog(
                        autoOpen: true,
                        maxWidth:400,
                        maxHeight: 200,
                        width: 400,
                        height: 200,
                        modal: true,
                        open: function(event, ui) 
                            setTimeout(function()
                                $('#dialog').dialog('close'); 
                            , notifyBefore * 1000);
                        ,
                        buttons: 
                        "Yes": function()   
                             $.get("/about", function(data,status)
                               // alert("Data: " + data + "\nStatus: " + status);
                              );                             
                            $('#dialog').dialog("close");
                            loadDialog();
                        ,
                        "No": function()   
                            $('#dialog').dialog("close");
                        
                       ,
                       close: function() 
                    );
                  );
            , (sessionAlive - notifyBefore) * 1000);
    ;

    loadDialog(); 
</script>

HTML 分区:

<div id="dialog" title="Session Timeout Info" style="display:none">
  <p>
    Your session will be timeout within 30 seconds. Do you want to continue session?  
  </p>
</div> 
</code>

【讨论】:

这给出了这个错误:TypeError: $(...).dialog is not a function【参考方案4】:

试试这个代码。希望它能解决你的问题。谢谢

var cookieName = 'sessionMsg';
var message = 'Your session is going to be end by 5 min, Please click OK to continue';

function getCookie(name)

    var name = name + "=";
    var ca = document.cookie.split(';');
    for(var i=0; i<ca.length; i++)
    
        var c = ca[i].trim();
        if (c.indexOf(name)==0) return c.substring(name.length,c.length);
    
    return "";


function setSessionPrompt() 
    var timeout = getCookie(cookieName) - new Date().getTime();
    setTimeout(function()
        if (new Date().getTime() < getCookie(cookieName)) 
            setSessionPrompt();
         else 
            if(confirm(message)) 
                // do your action here
            
        
    , timeout);


setSessionPrompt();

【讨论】:

【参考方案5】:

你知道吗 windows.setTimeout

http://www.w3schools.com/jsref/met_win_settimeout.asp

这是你需要的

例如

var resetTime_int;
function resetTimer()
    if(resetTime_int) window.clearTimeout(resetTime_int)
    resetTime_int=window.setTimeout(function ()
    if(prompt('Your session is going to be end by 5 min, Please click OK to continue'))     
    location.reload()
    , 1000*60*25)


resetTimer()
document.onmousemove=resetTimer
document.onkeyup=resetTimer

1000*60*25 = 25 分钟。

【讨论】:

他需要一种服务器端方法。只有在 idle 30 分钟后,用户才会注销。这将警告用户忽略这一事实。 假设用户在 12:00 登录。他们与网络应用程序交互直到 12:05。用户应在 12:35 注销,从而在 12:30 收到警告。用你的方法,他们会在 12:25 收到警告。 如果用户与 web 应用程序交互,服务器将不知道它。如果用户在做一些 ajax,你需要重置计时器。 大多数时候,服务器会知道它,除非一切都完全是客户端,没有任何 AJAX。 是的山姆..你是对的。我需要用户的非活动间隔时间。如果它达到 25 分钟,那么我只需要显示消息。使用 Amina 方法,它将在登录 25 分钟后显示消息。如果我错了,请纠正。【参考方案6】:

您应该使用 WebSockets 将数据从 Web 应用程序发送到客户端浏览器。

1) 计算服务器端的会话超时。 2) Websocket 会发送会话超时消息。

【讨论】:

【参考方案7】:

您可以在每个请求上发送一个带有剩余时间(以毫秒为单位)的 cookie。然后您可以按照建议使用 setTimeout 但在执行超时功能时再次测试该值。如果值已更改,您可以重置超时。由于 cookie 是为整个域设置的,因此即使对于 ajax 或其他选项卡,它也始终是正确的。

var cookieName = 'sessionMsg';
var message = 'Your session is going to be end by 5 min, Please click OK to continue';

function getCookie(name)

    var name = name + "=";
    var ca = document.cookie.split(';');
    for(var i=0; i<ca.length; i++)
    
        var c = ca[i].trim();
        if (c.indexOf(name)==0) return c.substring(name.length,c.length);
    
    return "";


function setSessionPrompt() 
    var timeout = getCookie(cookieName) - new Date().getTime();
    setTimeout(function()
        if (new Date().getTime() < getCookie(cookieName)) 
            setSessionPrompt();
         else 
            if(confirm(message)) 
                // do your action here
            
        
    , timeout);


setSessionPrompt();

【讨论】:

以上是关于在会话超时之前警告用户的主要内容,如果未能解决你的问题,请参考以下文章

如何在 shiro 中弹出一个屏幕来警告会话超时?

如何显示足够智能以处理多个打开的浏览器或选项卡的会话超时警告

如何使用JQuery和ColdFusion处理会话超时警告?

春季/安全中的自定义会话超时

Spring Security 中是不是存在会话超时异常?

常规会话管理和常见超时