关于Session和Cookie

http协议是一种无状态协议,一旦数据交换完毕,客户端与服务器端的连接就会关闭,再次交换数据需要建立新的连接。这样有个巨大的缺陷,就是服务端无法识别和跟踪客户端会话,即无法做到在服务端为每个客户端保存一份属于该客户端的数据,这个在实际应用中是行不通的。那要怎么解决呢?

        解决方法一: 可以通过将数据写入到客户端的Cookie中,做到服务端和客户端同步并共享该数据。但是Cookie有以下弊端:

  • Cookie数据存储在客户浏览器中,安全性较低;
  • 每一次请求,都会将全部的cookie传输到服务端,消耗带宽;
  • Cookie对存储的数据量有限制,单个Cookie保存的数据不能超过4K,且很多浏览器对Cookie的数量有限制;

        Cookie不能跨域,每个Cookie都是设置在当前域名的根域或当前域名的下级路径中的。

Session

        解决方法二:将数据存储在服务端Session中,大致流程如下:客户端发起请求,由服务端生成一个唯一的会话ID,然后通过Response的set-Cookie,写入到客户端Cookie(这个cookie叫做Session Cookie,通常这个Cookie的名称是JSESSIONID),之后所有的请求通过这个会话ID可以找到服务端存储的对应的数据。Session有以下几个需要注意的地方:

  • session创建: 在java web站点中,session的创建并不是以第一次请求而创建,而是在服务端第一次执行 HttpServletRequest.getSession(true) 语句时才会创建。那为什么很多站点在打开首页后,我们通过查看Cookie,却能看到生成了Session Cookie呢?这是因为在JSP中,如果JSP没有显示的使用 <% @page session=”false”%> 关闭session,则JSP文件在编译成Servlet时将会自动加上这样一条语句 HttpSession session = HttpServletRequest.getSession(true);这也是JSP中隐含的 session对象的来历。而很多网站的首页其实就是一个JSP页面,所以在编译成Servlet的时候,自动执行了HttpServletRequest.getSession(true)。

  • session销毁:session的销毁,主要通过以下几个途径:

    • session超时,session超时时间可以在中间件服务器中配置,也可以在web.xml中配置,通常设置30分钟超时;
    • 程序调用HttpSession.invalidate()方法;
    • 服务器关闭或停止;
  • session数据是存储在服务内存中的,所以大量的session会占用很多的服务器资源,可以将session持久化到单独的服务器,比如redis;

  • 浏览器会话和session会话是两个概念,浏览器会话关闭并不会使当前session会话销毁,当再次打开一个浏览器会话,会重新生成一个session会话,并将新产生的数据存储在新的会话中。

  • 集群部署的服务,需要考虑session的同步;

了解上面的知识后,可以考虑我之前遇到的两个问题: 1.在一个顶级域名xx.com下有多个二级目录,指向的是不同厂家开发的独立的服务,用户在xx.com/A登录后,跳转到xx.com/B 后,xx.com/A的登录信息就丢失了; 2.在移动端APP嵌套的H5页面中,出现图形验证码一直验证失败的情况(验证码生成后是保存在session中的)。

坚持原创技术分享,您的支持将鼓励我继续创作!
分享