Session深度揭秘

Session深度揭秘

在Web应用中,Session对象存储用户会话所需的属性及配置信息,实现会话保持和跟踪,本文将详细总结Session相关的知识点。

Session是什么

HTTP协议是一种无状态的协议,用户通过浏览器访问服务端的每次请求都是相互独立的,服务端无法直接通过HTTP请求来判断上次请求的用户和本次请求的用户是否是同一人,当然,你可以使用Cookie来传递用户状态的标识,但是每次发起请求都必须来回传递这些Cookie数据,为了实现更多的状态跟踪,传递的Cookie数据会越来越多,这无形中增加了浏览器与服务端的数据传输的压力和复杂性,Cookie的大小不仅有限制,而且这种方式是不安全的,容易被盗取和篡改,然而session的出现正解决了这些问题。session是存储于服务端的、用于记录和保持某些状态的一种会话跟踪技术。用户通过浏览器发起请求的时候,不用每次都回传所有的Cookie值了,只要回传一个key-value的键值对就可以了,一般情况下这个key为JSESIONID,value为客户端第一次访问服务端时生成的唯一值,这个value可以标识和跟踪用户的会话信息,这个value在服务端被习惯称作sessionId。

如何传输sessionId

客户端可以通过以下三种方式将JSESSIONID的key-value键值对传递到服务端。

1.如果用户浏览器不支持Cookie或Cookie被禁止了,浏览器将会把这个key-value键值对重写到请求的URL参数中,重写的格式如/xxx/path/abcAction;key=value?paramName=paramValue,其中的key-value就是要传递的参数。服务端接收到请求后,会从URL中取到这个key对应的value,并将这个value设置到request,具体的代码是request.setRequestedSessionId。

2.如果浏览器支持Cookie,则浏览器在发请求的时候将会在Request Headers中设置key-value的请求参数,服务端接收到请求后,将会取出这个value值,同时这个value值会覆盖掉从URL中取得的值。

3.基于SSL,默认情况下不支持,只有connector.getAttribute("SSLEnabled")为true时才支持。

如何实现保持会话

正常情况下,用户第一次通过浏览器请求服务端的时候是没有value的,此时服务端会通过request.getSession()方法创建一个HttpSession对象,并给它设置一个有效期,然后将这个对象存储在sessions的容器中,同时会把sessionId返回给浏览器端。如果用户再次发起请求,服务端在解析得到sessionId后,会判断sessionId对应的HttpSession是否存在,如果不存在,会创建一个HttpSession对象,并将这个对象存储在sessions的容器中,同时会把sessionId返回给浏览器端;如果存在,将可以得到对应的HttpSession对象,这个HttpSession对象可以存储很多状态或表示数据,如session.setAttribute(),从而实现会话跟踪。

session对象都有一个有效期,一般情况下,应用容器都会有一个后台线程用于检查每个session是否失效,如果失效将会被清除。而值得注意的是,调用request.getSession()时会检查对应的session对象是否过期,如果过期将会创建一个新session对象。

在应用容器重启或关闭的时候,未过期的session对象会被持久化到一个SESSIONS.ser文件中,当应用容器再次启动的时候,会重新读取SESSIONS.ser中所有未过期的session对象,并将它们存储到sessions集合中。一个应用服务器存储一套session数据。