`

捕捉登出时间解决方案-----java中session的正确理解

阅读更多

转载:http://www.51testing.com/?uid-88979-action-viewspace-itemid-108403

 

 前段时间要做一个捕捉用户登入和登出时间的功能,查了很多资料,做了很多测试,总结出两套方案,其中对session有了进一步的认识。

 

     用户的登入时间很好做了,在用户验证成功通过后,得到当前系统时间记录就行;如果系统用的是Acegi的话,可以写一个类,继承Acegi中的 AuthenticationProcessingFilter.java,并覆盖其onSuccessfulAuthentication方法,故名思 意,这个方法就是acegi在对用户成功通过时进行的一个附加操作的方法,在这个方法里你可以记录当前用户id、时间、ip等等日志信息到数据库中。

 

      但要捕捉用户的登出时间确实是很麻烦,首先要知道是http是无状态连接协议,当用户不通过注销方法登出而直接关闭浏览器或者结束进程时,服务器根本无法 捕捉这个事件,不管客户端发生了什么服务器也不知道,用户仅仅从服务器那得到了一个sessionid存储在浏览器进程的内存中或者cookie中,网上 很多说用window.onunload( )等js方式来捕捉用户登出事件其实也其不通,因为用户可以直接杀死进程或者在新窗口页中打开链接,然后把原窗口关闭,这时通过js捕捉到关闭浏览器事件 并发送请求告诉服务器,但其实用户还并没有离开系统,只不过换了个浏览器浏览页面。还有就是通过session过期来捕捉,但在系统正常运行下 session死亡只有两种可能:

1.session的持有者(即客户端浏览器)在最大无活动等待时间(MaxInactiveInterval)内无任何响应或请求  
2.session 被调用invalidate()方法强制弊而当用户关闭了浏览器后标志着session将不再发送请求到服务器,服务器也不会无缘无故调用它的 invalidate()方法,这样session只能等到time-out时才会销毁,如果系统设置了session的 MaxInactiveInterval为-1的话,那这个session将永远存活到服务器关闭为止。

所以session不能反应出用户的活动状态,浏览器关闭事件也不能完全得出用户一定是退出了系统。

 

     那这个登出时间到底怎样才能得到呢?事实如此,只能降低期望了,和老大讨论了许久,最后只有两套方案行得通,如下。

 

 一, 以性能换精度,也是我最终采用的方案,我们可以精确地得到用户登入时间,而登出时间我们得到个大概的时间就行,不需要太精确,毕竟系统不是什么很机密性的 东西。采用session监听器来实现,写一类,继承HttpSessionListener,实现其public void sessionDestroyed(HttpSessionEvent arg0) 和public void sessionCreated(HttpSessionEvent arg0) 方法,当用户session失效时会走sessionDestroyed方法,在其里面得到的当前时间就是用户的大概登出时间,前提是系统session 过期时间不能设置太长,要不误差就太大了,半小时就差不多。

 

二, 以精度换性能,b/s系统的页面一般都会带有头部、脚部页面或者是框架型的,这样我们就可以在公用的头脚或主框架页中插入一个隐藏的iframe或者代码 块。里头写一段js方法,window.setInterval()之类的,每隔一小段时间(假设为2分钟)向服务器发送一个空请求,目的仅仅是让服务器 知道客户端还开着我的页面,不管是以哪种方式。服务器接受这个请求后,新建一个Map对象(新建一javabean类也行,里面有用户id和请求时间两个 属性),put两个元素,当前用户id为value,一约定代号为key,如“userid”,另一元素请求时间为value,同样一约定代号为key, 如“requesttime”;然后再以这个对象为value,sessionid为key ,set一个attribute到session当中,当下次再收到一个请求时,再重复上部操作,这样请求时间会不断更新。做完这些之后,还需要添加一个 定时调度的job,每隔一小段时间(假设为3分钟),遍历session对象,从其中的map或者javabean中取出userid 和 requesttime,判断这个请求时间和当前时间的时差是否大于三分钟,如果是则说明用户已经没有再向服务器发送请求,即没有页面再用户端打开着,用 户离开了,记录最后一次请求时间,也就是用户的登出时间。

 

       目前还没有想到其它更好的方法,现在这种机制下好像也只能这样了,还有一点需要注意,如果采用在用户登录成 功时记录登录时间的方式,在要求并发数较大的时候不可行,今天对我们项目组做的一个系统进行登录过程50、100用户并发测试时,失败率极高,而问题就出 在登录时向数据库记录登入时间和更新最高访问人数时出现的sql事务死锁情况,所以后来更换了方案,在登录时将当前时间为value,sessionid 为key,set到session当中,当这个session过期时,通过httpsessionlistener捕捉到该事件,从session中取出 该用户的登录时间和当前时间一并存入数据库,后者作为登出时间;最高访问人数也放在了application里,这样性能上提高了不少。

 

        如果要得到用户的在线时间的话,需要注意的是,由于一个浏览器进程共用一个session,一个浏览器中的所有标签也是共用一个session,在用户登 录成功时需要通过当前sessionid判断用户是否重复登录了,如果是则在此时就不应该将当前时间set到session中,而应该保持上次存储的登录 时间。

 

 

/*********** 下面再引入一下网上比较经典的描述,更有利于理解session和cookie ************/

让我们用几个例子来描述一下cookie和session机制之间的区别与联系。笔者曾经常去的一家咖啡店有喝5杯咖啡免费赠一杯咖啡的优惠,然而一次性消费5杯咖啡的机会微乎其微,这时就需要某种方式来纪录某位顾客的消费数量。想象一下其实也无外乎下面的几种方案:
1、该店的店员很厉害,能记住每位顾客的消费数量,只要顾客一走进咖啡店,店员就知道该怎么对待了。这种做法就是协议本身支持状态。
2、发给顾客一张卡片,上面记录着消费的数量,一般还有个有效期限。每次消费时,如果顾客出示这张卡片,则此次消费就会与以前或以后的消费相联系起来。这种做法就是在客户端保持状态。
3、 发给顾客一张会员卡,除了卡号之外什么信息也不纪录,每次消费时,如果顾客出示该卡片,则店员在店里的纪录本上找到这个卡号对应的纪录添加一些消费信息。 这种做法就是在服务器端保持状态。由于HTTP协议是无状态的,而出于种种考虑也不希望使之成为有状态的,因此,后面两种方案就成为现实的选择。具体来说 cookie机制采用的是在客户端保持状态的方案,而session机制采用的是在服务器端

保持状态的方案。同时我们也看到,由于采用服务器端保持状态的方案在客户端也需要保存一个标识,所以session机制可能需要借助于cookie机制来达到保存标识的目的,但实际上它还有其他选择。

分享到:
评论
1 楼 abiaocom 2011-12-08  
说实话,session这个东西不太好弄,第二种方法看上去可行,可实际上跟第一种方法差不多。我搞.net的,在页面中放一个timer计时器让它每两分钟向数据库更新一次当前时间。虽然我知道,页面关闭后session值还存在,自以为timer总该死了吧,不会更新数据库了吧。。。没想到它还在更新,直到session死掉,当前会话结束才罢休。不只这样,即使页面关闭后,页面中的textbox等这些控件也没死掉。

相关推荐

    Javaweb项目session超时解决方案

    Javaweb项目Session超时解决方案 在Java Web开发中,Session机制为我们提供了许多方便,Session是由浏览器和服务器之间维护的。Session超时理解为:浏览器和服务器之间创建了一个Session,由于客户端长时间(休眠...

    java中使用session模拟用户登陆

    在Java Web开发中,Session是服务器端用于跟踪用户状态的一种机制。当用户通过用户名和密码登录系统后,服务器需要一种方式来识别这个已验证的用户,以便在后续的请求中提供个性化的服务,例如访问权限控制。这时,...

    JAVA SESSION监听器

    Java Session监听器是Java Servlet规范中提供的一种机制,用于对HttpSession对象的生命周期事件进行监听和处理。在Web应用程序中,Session是用来跟踪用户状态的重要工具,特别是在无状态的HTTP协议上。当用户登录后...

    理解session机制

    总的来说,Session机制是Web应用程序中维持用户状态的关键技术,理解和正确使用Session对于开发高效、安全的Web应用至关重要。开发者需要根据具体的应用场景选择合适的Session管理策略,以保证用户体验和系统性能。

    Laravel开发-session-auth

    例如,当用户成功登录后,Laravel会将用户ID存储在session中,以便在后续请求中识别用户。`auth`中间件会检查session中的用户ID,如果没有找到,就会拒绝访问受保护的资源。 **4. 自定义实现** Laravel允许开发者...

    通用安全的token化解决方案-美化版.pdf

    【通用安全的token化解决方案】 Token化是一种网络安全技术,它涉及到将敏感数据(如用户凭据)转换为无意义的令牌,以便在网络通信中...在设计和实施这类解决方案时,理解其核心原理、潜在风险和应对策略至关重要。

    Laravel开发-session-tokens

    在Laravel框架中,Session和Tokens是两个非常关键的安全机制,它们在开发过程中扮演着确保用户身份认证和数据安全的角色。本篇文章将深入探讨Laravel的Session机制以及独特的"记住我"功能,其中涉及到的"session-...

    cas单点登出的3个类

    在描述中提到的“CAS单点登出问题及解决”,暗示了在实际操作中可能会遇到一些挑战,比如跨域问题、登出通知不及时等,需要通过特定的技术手段来解决。在这个过程中,通常会涉及到以下三个关键类: 1. **Simple...

    微信小程序session实现smallapp-session-master.zip

    总之,`smallapp-session-master`项目为我们提供了微信小程序中用户会话管理的一个实际示例,它展示了如何安全、有效地实现登录状态的保持,对于理解和实践微信小程序的用户认证与授权机制非常有帮助。通过研究这个...

    Java单点登录解决方案

    - Keycloak:基于Java的开放源代码身份和访问管理解决方案,支持OAuth 2.0、OpenID Connect等现代标准。 3. SSO实现步骤 (1) 配置CAS服务器:安装并配置CAS服务器,设置认证策略和数据库连接等。 (2) 创建服务提供...

    Java Web程序设计入门课件-Session对象.pptx

    总的来说,Session是Java Web开发中保持用户状态的关键工具,正确理解和使用Session能够帮助构建更高效、安全的Web应用。在设计Web应用时,需要注意合理设置Session超时时间,平衡用户体验和服务器资源的利用。

    cas实现单点登录,登出(java和php客户端)

    总之,CAS单点登录系统为多应用环境提供了一种高效的身份验证解决方案。通过Java和PHP客户端的集成,可以在多种技术栈的项目中实现一致的用户体验,同时也简化了用户管理和权限控制。在实际应用中,应根据项目需求...

    Java中设置session的详细解释.docx

    5. **Java中的HttpSession**:在Java Web开发中,`javax.servlet.http.HttpSession`接口代表了一个Session对象,开发者可以通过这个接口来创建、读取、更新或删除Session中的数据。 **二、HTTP协议和状态保持** 1. ...

    JAVA应用开发日志解决方案

    ### JAVA应用开发日志解决方案 #### 1. 简介 在软件开发与维护过程中,日志记录是至关重要的环节之一。通过日志记录,开发者可以追踪程序运行过程中的状态变化,帮助诊断错误和异常情况,从而提高系统的稳定性和可...

    一个关于Session的小demo

    1. **初始化Session**:在JSP页面中,我们可以使用`<jsp:useBean>`标签或者Java代码来创建一个新的Session。例如: ```java HttpSession session = request.getSession(); ``` 2. **设置Session属性**:一旦...

    ssh修改超时自动登出时间的方法

    如果不通过tmux这些辅助工具来维持session的话,那么我们需要通过修改服务器的登出时间来防止自动登出。 修改步骤 首先我们看一下服务器上的自动登出时间是多少: $ echo $TMOUT 如果什么都没有输出,那么表示你的...

    java DWR实现一个用户在同一时间只能登录一次的解决方案

    本解决方案主要关注如何利用DWR来实现一个用户在同一时间只能登录一次的功能,类似于QQ的单点登录机制。 首先,我们需要理解DWR的基本工作原理。DWR允许JavaScript直接调用服务器端的Java方法,并将结果返回到...

    Session登录注销

    在IT行业中,尤其是在Web开发领域,`Session登录注销`是一个重要的概念,主要涉及到用户身份验证、安全性以及数据传输。本文将详细阐述`session`在登录和注销中的作用,以及`JSP`和`servlet`之间如何进行数据传输。 ...

Global site tag (gtag.js) - Google Analytics