当前位置: 首页 > 技术随笔 > 如何防止session超时

如何防止session超时

众所周知,当用户登录网站后较长一段时间没有与服务器进行交互,将会导致服务器上的用户会话数据(即session)被销毁。此时,当用户再次操作网页时,如果服务器进行了session校验,那么浏览器将会提醒用户session超时。

那么,如何解决用户登录后较长时间未操作而导致的session失效的问题呢?

导致这个问题的关键词有两个:一个是「长时间」,一个是「未操作」。
1、如果用户未操作的「长时间」超过了服务器配置的session超时时间,并导致session失效,那么我们延长session的超时时间,让用户原来的「长时间」与超时时间相比,变得不「长」,不就可以解决了吗?
2、如果用户是长时间「未操作」导致session失效,那么我们想办法产生「操作」,让用户每隔一小段时间就「操作」一次,与服务器产生交互,那么session自然也不会失效。 一般情况下下,我们首先想到的是,通过改变服务器的配置,延长服务器的session超时时间。 例如,在Tomcat服务器的web.xml文件中有如下节点内容:

<session-config>
	<session-timeout>30</session-timeout>
</session-config>

这里的30表示session的超时时间,单位为分钟,如果用户登录后在30分钟内没有与服务器交互,那么当前用户的session将失效。我们可以配置一个更大的数值(比如60),就可以延长session的超时时间,如果将该值改为0或负数的话,则表示session永不失效。

不过在实际的工作应用中,一味地上调session的超时时间设置并不怎么常见,大多数需要实现该功能的网站都将解决问题的焦点集中在第二条思路上。例如:一些在线网站均采用定时刷新页面的方法来防止session超时。

定时刷新页面,最常见的有两种实现方式:一种是通过JavaScript + HTML DOM,另一种则是通过meta标签来实现。

function refresh(seconds){
	setTimeout("self.location.reload()", seconds * 1000);
}
refresh(600);  //调用方法启动定时刷新,数值单位:秒。

在页面中添加meta标签refresh也可以指定每隔指定时间就刷新当前页面,示例代码如下:

<meta http-equiv="refresh" content="600" />

上述meta标签可以实现每过600秒就刷新一次当前页面。

在上述两种方案中,较好的为第二种,因为如果当前页面是在IE浏览器的模式窗口中打开的,默认情况下,self.location.reload()方法将会失效,而refresh meta标签在IE模式窗口下仍然有效。

上述两种方式都实现了刷新当前页面,并且使用起来非常简单,不过很遗憾的是,它们存在一种几乎致命的缺陷。 试想一下,如果在论坛发帖等需要用户输入内容的页面,用户花费较长的时间输入了许多文本内容,可是突然遇到了一个定时页面刷新,结果用户输入的所有内容都没了,估计这个时候用户连掐死你的心都有了……

因此我们需要在当前页面本身不刷新、不影响用户的任何操作的情况下实现定时刷新。最常见的解决方法仍然有两种。 一种是在当前页面添加一个隐藏的iframe,然后在该iframe里面实现定时刷新。

<iframe id="hidden_iframe" style="display:none;" scrolling="no" frameborder="0" name=" hidden_iframe " src="ping.php"></iframe>

此外,我们需要在服务器上编写对应的请求响应代码,例如ping.php中可以编写如下代码:

<?php
//每隔600秒刷新当前页面
echo '<html><head><meta http-equiv="refresh" content="600" /></head><body></body></html>';
?>

另外一种则是使用JavaScript Image对象来实现定时刷新,JavaScript代码如下:

function autoRefresh(seconds){
    if(typeof period == "undefined"){   //如果是第一次执行
        period = seconds * 1000;    //定义全局变量period
        var bodyDOM = document.getElementsByTagName("body")[0];
        if(bodyDOM){
            bodyDOM.innerHTML += '<img id="auto_refresh_img" src="" style="display:none" />';   //添加隐藏的图片
            imgDOM = document.getElementById("auto_refresh_img");   //定义全局Image对象
        }
    }
    if(typeof imgDOM != "undefined"){
        imgDOM.src = "ping.php?sid=" + new Date().getTime();    //防止缓存
        setTimeout("autoRefresh(" + seconds + ")", period);     
    }
}
autoRefresh(600);   //调用方法启动定时刷新

和使用iframe来实现定时刷新一样,使用JavaScript Image对象实现定时刷新,也需要在服务器端编写类似的请求响应代码。服务器的响应可以是文字等非图片内容,非图片内容只会造成图像加载失败,而我们的图像标签本身就是隐藏的,不管是加载成功还是失败都不会显示,毕竟我们的主要目的是发送请求给服务器,让服务器保持session处于活动状态。

当然,我们还可以使用Ajax来实现定时刷新,不过使用Image对象会更好一些,因为有些老式浏览器的JavaScript无法实现Ajax,但是却可以使用Image对象。此外,使用Ajax需要编写更多的代码来处理XMLHttpRequest等对象的活动。

在上述两种方式中,各有其优缺点。

使用iframe标签实现定时刷新的优点是:不需要编写JavaScript代码,可以在浏览器禁用JavaScript的情况下实现定时刷新;其缺点是:在某些不支持iframe标签的老式浏览器中没有效果,此外,iframe标签在浏览器中新增加了一个独立的页面,即使没有显示出来,不过其内部解析的windowdocument等对象仍然存在,占用的浏览器内存相对较多。

使用Image对象的优点是:与iframe相比,占用的内存相对较少,支持Image的浏览器也相对较多(现代浏览器均支持);缺点是:在浏览器禁用JavaScript的情况下就毫无用武之地了。

开发人员应根据实际需求情况来确定使用何种实现方式更好。此外,服务器在响应定时刷新的请求时,在满足要求的情况下,应返回尽可能少的数据,以节省带宽。

30 5
我们认为: 用户的主要目的,是为了获取有用的信息,而不是来点击广告的。因此本站将竭力做好内容,并将广告和内容进行分离,确保所有广告不会影响到用户的正常阅读体验。用户仅凭个人意愿和兴趣爱好点击广告。
我们坚信:只有给用户带来价值,用户才会给我们以回报。
CodePlayer技术交流群1CodePlayer技术交流群1

帮朋友打一个硬广告:

P2P网贷系统(Java版本) 新年低价大促销,多年P2P技术积累,系统功能完善(可按需定制,可支持第三方存管、银行存管),架构稳定灵活、性能优异、二次开发快速简单。 另可提供二次开发、安装部署、售后维护、安全培训等一条龙服务。

外行看热闹,内行看门道。可以自信地认为,在系统设计上,比市面上的晓风、迪蒙、方维、绿麻雀、国融信、金和盛等P2P系统要好。
深圳地区支持自带技术人员现场考察源代码、了解主要技术架构,货比三家,再决定是否购买。

也可推荐他人购买,一旦完全成交,推荐人可获得实际售价 10% 的返现。
有意向者,详情请 点击这里 联系,工作时间立即回复。