`

捕捉登出时间解决方案-----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超时解决方案,关于解决方案分类比较明确,内容详细,需要的朋友可以参考下。

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

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

    SpringMVC-Mybatis-Maven-MySQL 登录登出并校验用户且写入session的demo

    这是一个Spring-SpringMVC-Mybatis-Maven-MySQL架构的Java项目,主要实现登录校验功能。...显示页面有登出按钮,点击之后回到登录页面,并去掉session中的用户信息。properties包中带有.sql建表文件

    JAVA应用开发日志解决方案

    JAVA应用开发日志解决方案主要是log4j的配置和使用

    cas-overlay-template-6.4 服务端代码

    9.CAS-登出 10.CAS-redisCluster集群存储ticket(相应redis必须配置成cluster集群) 11.CAS-加密存储ticket 12.CAS-实习动态验证码 13.CAS-实习自定义登录 14.CAS-实现自定义返回用户登录信息 15.CAS-页面缓存记住我...

    监视用户的登入登出和页面推送技术

    监控用户的登入登出系统,并根据用户将信息推送到页面 用到jquery1.5 dwr3.0 包括: java源码 ,js源码, web.xml配置 希望对大家有所帮助

    Session登录注销

    http://blog.csdn.net/qq_22778717/article/details/52622259 两个点 一个是session登录注销 一个是jsp和servlet间数据传输的配置

    springboot整合Sa-Token 实现前后端分离登录注销功能,刚学习Sa-Token,用来练手,适合初学者。仅作学习使用

    springboot整合Sa-Token 实现前后端分离登录注销功能,刚学习Sa-Token,用来练手,适合初学者。仅作学习使用 前端使用html jquery ajax异步请求 后端springboot框架,Sa-Token框架。 jdk使用1.8 mysql 8.0

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

    NULL 博文链接:https://zxs19861202.iteye.com/blog/855856

    Nodejs进阶:express+session实现简易登录身份认证

    本文基于express、express-session实现了简易的登录/登出功能,完整的代码示例可以在这里找到。 环境初始化 首先,初始化项目 express -e 然后,安装依赖。 npm install 接着,安装session相关的包。 npm ...

    cas单点登出的3个类

    CAS单点登出问题及解决 二 (文章摘自笔者发在自己公司内部论坛的文章:谢绝转载)

    cas单点登录登出配置demo

    cas单点登录登出配置 php 和java 版本。 完美实现了登录和登出, demo cas server 3.5.2 版本 -- 扔到tomcat下直接跑。 java客户端为 3.2.1. -- 要想跑的话需要自己下载jar php 扔到php工程里面直接跑。。 记得看...

    在线人员 ajax聊天室 关闭浏览器和登出控制使session失效

    在线人员 ajax聊天室 关闭浏览器和登出控制使session失效 功能基本完成。 可以查看我的博客。 直接下载即可运行。

    java毕设项目之基于java+springboot车辆管理系统.zip

    "Mysql数据库,Java语言,Spring Boot框架。 管理员功能模块的实现: - 个人中心 (5.1): 此模块用于管理员自身信息的管理,包括个人资料的查看、修改密码、登出等功能。 - 员工管理 (5.2): 这个功能模块用于管理...

    使用Java servlet实现自动登录退出功能

    主要介绍了使用Java servlet实现自动登录退出功能,,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下

    Vue后台管理

    - 登录/登出 - 权限管理 - 列表过滤 - 权限切换 - 多语言切换 - 组件 - 富文本编辑器 - Markdown编辑器 - 城市级联 - 图片预览编辑 - 可拖拽列表 - 文件上传 - 数字渐变 - split-pane - 表单编辑 - 文章...

    基于Java开发的OA办公审批系统源码+项目详细说明.zip

    基于Java开发的OA办公审批系统源码+项目详细说明.zip 该资源内项目代码都是经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等...

    java单点登录系统.zip

    1、boy-sso-example项目中直接在web.xml中添加如下代码,需要注意的是需要依赖boy-sso-client这个项目。 <filter-name>SSOAuth</filter-name> <filter-class>com.boy.sso.client.SSOFilter</filter-class> ...

    lockit:Express的身份验证解决方案

    Lockit是的身份验证解决方案。 查看。 它由多个单一目的模块组成: 目录 快速开始 完整安装 配置 数据库连接 发送邮件 自定义视图 大事记 报名 登录 登出 删除 忘了::已发送 忘了::成功 REST API 样本配置 特征 ...

Global site tag (gtag.js) - Google Analytics