简介

session(会话),其实是一个容易让人误解的词。它总跟web系统的会话挂钩,利用session,javaweb项目实现了登录状态的控制。坊间流传,关闭浏览器,就是关闭了web系统的会话。

其实浏览器对于会话有自己的定义,而web系统对于会话也有自己的定义。在tomcat中,session通常是指实现了HttpSession接口的实现类。并且不存在关闭浏览器就会关闭tomcat的HttpSession这种状况。

session本身并不难,如果只是做登录校验之类的功能,并不需要深入了解,但难的是session和cookie的结合使用,在不同情况下浏览器对cookie的控制行为所涉及到的诸多细节,我搜查了很多资料,查看过tomcat源码,亦是没有找到全面的概述。

当然我并未看过、也不知道去哪里看比较全面的关于浏览器对cookie的控制资料,如果有知道的大神,还望留言链接。本文题目,之所以说是探讨,而不是了解或者介绍,因为我自己也卡在了某个点上,由于时间关系,我不能花太多时间去研究,但又不忍心就此放弃,所以先记录下来,日后有机会再研究,这期间如有大神指点,也许能让我茅塞顿开。

session本质

我用的是javaweb项目,因此这里的session特指HttpSession。先来看下tomcat源码中对session的设计,在org.apache.catalina.session包下,有如下设计:

 

平时所用到的HttpSession的实现类就是这个standardSession。但是所获取的HttpSession实例确是外观类StandardSessionFacade,其屏蔽了许多方法,但也增强了安全性。

HttpSession提供了一些方法,来控制session或者获取session的状态,如获取session的id,获取session的创建时间,设置session的attribute,使session失效等。值得一提的是session的attribute其实是一个线程安全的hashMap

 

但是,创建session、根据id获取session的方法并不在这里,而是在一个管理器中,其设计如下:

 

ManagerBase是实现了Manager接口的抽象类,实现了管理session的功能。其实现子类PersistentManagerBase拓展了将session持久化的功能。但是这里不需要讲到其子类。看ManagerBase中的一段代码:

 

由此可知,所谓的session,其实就是一个用线程安全的hashMap存储起来的实现了Session接口的standardSession对象,在hashmap中以其id为key,自身为value。

再看获取session的方法,一目了然:

 

这个方法是在什么时候调用的呢?当浏览器访问系统时,request会解析请求中携带的jssesionid,用它去找到存在于应用中的session,但是如果没有找到,那么就会调用session的创建方法,并且生成一个新的jssessionid,返回session。

总而言之,session是存在于线程安全的map中的值,可以通过id找到,也可以使用invalidate方法销毁,但绝不会是浏览器关闭,就能对它进行销毁的。

cookie简介

提到session,那么cookie是不得不说的。至于cookie是什么,我就不多说了,大家都懂。直接看其内容吧:

 

这是一次http请求中(http://localhost:8080/test1),包含的请求和响应信息,是对一个系统的初次访问,用的是谷歌浏览器。

请求头中,包含的Cookie信息,并没有上文提到的jsessionid, 那是因为这是对系统的初次访问,系统还没生成session。但是访问之后,系统就会生成一个session,而且,会在响应流中设置响应头Set-Cookie,其值为JESSIONID=xxx。这样浏览器对localhost:8080和cookie的联系就有了记忆,浏览器会将其存储起来,可在调试工具中看到:

 

那么再次访问http://localhost:8080/test1, 浏览器会主动在请求头添加包括jsession的cookie信息

 

系统根据这个jsessionid找到session,也就不会在响应头中添加Set-Cookie信息。

这里说一下cookie中的两个重要属性:

domain表示的是cookie所在的域,默认为请求的地址,如网址为www.test.com/test/test.aspx,那么domain默认为www.test.com。而跨域访问,如域A为t1.test.com,域B为t2.test.com,那么在域A生产一个令域A和域B都能访问的cookie就要将该cookie的domain设置为.test.com;如果要在域A生产一个令域A不能访问而域B能访问的cookie就要将该cookie的domain设置为t2.test.com。

path表示cookie所在的目录,默认为/,就是根目录。在同一个服务器上有目录如下:/test/,/test/cd/,/test/dd/,现设一个cookie1的path为/test/,cookie2的path为/test/cd/,那么test下的所有页面都可以访问到cookie1,而/test/和/test/dd/的子页面不能访问cookie2。这是因为cookie能让其path路径下的页面访问。

疑点

下面,就该说下我的疑点了。

情况1:

但是当我在8081的一个方法中,重定向到8080的一个路径时,发现了奇怪的现象。

 

1、第一次访问8081/test

 

没有cookie,服务器设置set-cookie,正常。

2、第二次访问8081/test

 

cookie与上次的set-cookie一致,正常。

3、第一次访问8080/test1

 

浏览器把8081/test的cookie发过去了。8080的服务器找不到这个jsessionid,又重新设置了jsessionid,等到再次访问8081/test时,大家也能猜到会发生什么了吧。

推论

至此,我斗胆推论,浏览器会对同一ip不同端口的服务访问认定是可以进行cookie共享的,两个cookie的domain是一致的。而这种cookie的截图也一定程度上印证了我的想法:

 

cookie的domain似乎只认定域名,无关端口。

但是根据浏览器的同源策略,同域名不同端口的访问也应该是跨域的啊。除非浏览器的域跟cookie的domain在概念上是有区别的,对于这点,我没找到确切的官方资料,但网上大神是这么说的:

解决方案

基于上面的未查阅官方资料而做出的不严谨的推论,我想,只要完全避免同域的情况就可以避开这个问题。于是我把8081和8080系统分别部署在两个机器上。由于不同ip,这样无论如何,两个cookie都不会是同domain的了。果然,结果是没有问题的。

不足

虽然这个解决方案避开了同域的问题,但是没有彻底解决,毕竟同域的系统相互之间的访问也是有必要的,为此希望能获得更多的建议或者资料,补充这方面知识的不足,让我彻底解决这个问题。

扩展阅读

Cookie与Session的区别

面试常考!缓存三大问题及解决方案

死磕 Java 并发:深入分析 synchronized 的实现原理

深入理解正则表达式

聊聊前后端分离接口规范

作者:千里明月

来源:https://my.oschina.net/mingyuelab/blog/2986928

session深入探讨的更多相关文章

  1. 大型网站系统架构实践(六)深入探讨web应用集群Session保持

    原理 在第三,四篇文章中讲到了会话保持的问题,而且还遗留了一个问题,就是会话保持存在单点故障, 当时的方案是cookie插入后缀,即haproxy指负责分发请求,应用服务自行保持用户会话,如果应 用服 ...

  2. 今天一起探讨shiro实现账户同一时刻session唯一

    今天和同事在一起探讨shiro如何实现一个账户同一时刻只有一session存在的问题,下面小编把核心代码分享到博客园平台,需要的朋友参考下http://m.0834jl.com 今天遇到一个项目问题, ...

  3. asp.net 分布式探讨之Session共享问题

    ---恢复内容开始--- Session共享是分布式架构设计中的一大难点,尽管session共享的解决方案不少,但是.net 下的解决方案还是比较少,而且说明文档也很少. 之前尝试用memcached ...

  4. CAS Client集群环境的Session问题及解决方案

    [原创申明:文章为原创,欢迎非盈利性转载,但转载必须注明来源] 之前写过一篇文章,介绍单点登录的基本原理.这篇文章重点介绍开源单点登录系统CAS的登录和注销的实现方法.并结合实际工作中碰到的问题,探讨 ...

  5. Hibernate 系列 05 - Session 类

    引导目录: Hibernate 系列教程 目录 前言: Session是Hibernate运作的中心,对象的生命周期.事务的管理.数据库的存取都与Session息息相关. 就如同在编写JDBC时需要关 ...

  6. [转载]深入理解HTTP Session

    深入理解HTTP Session   session在web开发中是一个非常重要的概念,这个概念很抽象,很难定义,也是最让人迷惑的一个名词,也是最多被滥用的名字之一,在不同的场合,session一次的 ...

  7. ASP.NET探讨:技术的学习顺序问题

    作者: シtearシ  来源: 博客园  发布时间: 2011-09-27 08:40  阅读: 7675 次  推荐: 25   原文链接   [收藏]   摘要:很多人对于ASP.NET的入门和学 ...

  8. session的安全性

    提到session,大家肯定会联想到登录,登录成功后记录登录状态,同时标记当前登录用户是谁.功能大体上就是这个样子,但是今天要讲的不是功能,而是实现.通过探讨session的实现方式来发掘一些可能你之 ...

  9. session机制详解以及session的相关应用

    session是web开发里一个重要的概念,在大多数web应用里session都是被当做现成的东西,拿来就直接用,但是一些复杂的web应用里能拿来用的session已经满足不了实际的需求,当碰到这样的 ...

随机推荐

  1. 在vmware上MBR方式安装archLinux

    进入安装盘 设置好vmware的相关选项,进入下载好的系统中,显示如下 联网 输入以下命令,后面加&使其后台运行 dhcpcd & 然后ping一下检测是否联网 ping baidu. ...

  2. 使用dd命令快速生成大文件或者小文件

    使用dd命令快速生成大文件或者小文件 需求场景: 在程序的测试中有些场景需要大量的小文件或者几个比较大的文件,而在我们的文件系统里一时无法找到那么多或者那么大的文件,此时linux的dd命令就能快速的 ...

  3. CentOS 7环境下大量创建账号的方法

    1 一些账号相关的检查工具 1.1 pwck命令 pwck 这个指令在检查 /etc/passwd 这个账号配置文件内的信息,与实际的家目录是否存在等信息,还可以比对 /etc/passwd /etc ...

  4. e3mall商城的归纳总结6之redis

    一.说在前面的话 前面几节我们主要对该项目的后端进行了增删改查,但是所有的数据都是存放在数据库中,这样的话数据库的压力显而易见是很大的,因此本节学习nosql的缓存,也就是redis的使用,在使用之前 ...

  5. 安装Apache所踩的的坑

    刚开始接触PHP等一些脚本语言,需要建立一个本地的服务器,变进行安装了Apache.在其中碰到了诸多问题,和大家一一分享一下. 一.刚解压完成后使用cmd面板进入解压完成的apache的bin目录下, ...

  6. Asterisk-WebRTC客户端的部署

    很久没有写博客了.最近完成asterisk 和  jssip的库集成,浏览器支持chrome/firefox.在集成的过程中遇到了一些问题,在这儿分享出来,免得大家走弯路. 在网上看一些帖子,环境都是 ...

  7. Spring Boot 如何快速集成 Redis 哨兵?

    上一篇:Spring Boot 如何快速集成 Redis? 前面的分享栈长介绍了如何使用 Spring Boot 快速集成 Redis,上一篇是单机版,也有粉丝留言说有没有 Redis Sentine ...

  8. Unity资源引用问题

    前几天做项目时,遇到一个奇怪的问题: 从一处复制了一个预制体,预制体上面还附有一个材质球,材质球上关联着另一张贴图. 将所有关联的东西,均Copy两份,然后关联成一个新的预制体,最后用项目内的读取内存 ...

  9. 剑指 Offer 44. 数字序列中某一位的数字

    题目描述 数字以0123456789101112131415-的格式序列化到一个字符序列中.在这个序列中,第5位(从下标0开始计数)是5,第13位是1,第19位是4,等等. 请写一个函数,求任意第n位 ...

  10. [bash] 获取linux主机名,检视内中是否有特定字符串

    代码: #!/bin/bash hostname=$(hostname) #调用hostname命令获取主机名放入变量hostname中 #echo $hostname if [ `echo ${ho ...