HttpSession之坑:浏览器如何保证从cookie中解析并发送对应的sessionId到目标Url

文章的背景是浏览器的Cookie未被禁用.


我们知道,无论是session还是cookie都是在服务端创建的,只是cookie不同于session被保存在客户端。

工作流程如下:
这里写图片描述

  • 客户端第一次请求服务器,cookie中不存在与url相对应的sessionid。所以request headers 的cookie头里不包含sessionid的内容,甚至不包含cookie请求头;
  • 服务端调用 request.getSession(); ,没有sessionid自然无法取得相应的session信息,立即创建新的session;
  • 新创建的session信息被服务端存储下来,sessionid被添加到response的set-cookie响应头,并返回给客户端;
  • 客户端接收到response报文的cookie内容,并将其保存在本地;
  • 客户端再一次请求服务器,浏览器将根据url,解析出相应的sessionid,并添加到cookie请求头,发送给服务器;
  • 服务端调用 request.getSession(); ,根据sessionid从session存储里获得相应的session信息,然后进一步操作,再响应给客户端。

事实上cookie没那么神秘,它被抽象为一个实体类,包含着一系列属性和方法,如下:

    new Cookie(String name,String value) //创建cookie
    response.addCookie(Cookie cookie) //向response中添加cookie,可以多次调用以添加多个cookie
  getName() //获得cookie的name
  getValue() //获得cookie的value
  setValue(String newValue)  //用于修改name对应的value值。
  setMaxAge(int expiry) //设置有效时间,单位s,缺省-1,即关闭浏览器cookie失效
  setPath(String uri)  //设置路径  
  setDomain(String pattern) //设置域名,(一般浏览器会自动设置,服务端的操作无效)                   
  setDomain(".zyh.com") //如果这样设置,www.zyh.com / bbs.zyh.com 都可以访问,a.b.zyh.com无法访问
    isHttpOnly() //是否只能在服务端操作cookie,而客户端javascript不能。不是cookie规范,而是浏览器支持
  setComment(String purpose) //cookie的描述信息
  setSecure(boolean flag) //是否使用安全传输协议。为true时,只有用https请求时cookie才会被发
  //送给服务器端,而http时不会。但是客户端还是可以接收来自服务端的cookie。缺省 false
  setVersion(int v) //编译规范,默认0

对于客户端而言,cookie仅仅是一个对象实例,包含着keyvaluedomainpath等一系列附加信息序列化后被保存在客户端。而客户端可能同时保存着成百上千个这样的对象实例,确切的说是更像是cookie集合,类似于:List<Cookie>


那么浏览器到底如何保证从cookie中解析并发送对应的sessionId到目标Url呢?

  • 要理解浏览器如何解析出sessionid,首先要知道包含sessionid的cookie是如何被创建的:
Cookie sessionCookie = new Cookie("sessionid","1234");
sessionCookie.setPath("/path"); //可以在服务端设置
sessionCookie.setDomain("www.test.com"); //一般情况下domain被浏览器重新设置,服务端的设置无效
response.addCookie(sessionCookie);
  • List<Cookie>序列化存储在客户端,我们可以将它理解成一个数据表,表结构如下:
name value domain path other_info
 
  • 浏览器通过URL来访问服务端,URL可能是下面三种样式。在此之前要知道,无论是域名域名+端口还是ip地址+端口,对于Http*协议来说都是Domain
www.test.com/path/.. # 域名+路径
www.test.com:8080/path/.. # 域名+端口+路径,当然这种写法不常见,太丑了。
                          #通常在服务端域名配置的时候应该已经做好了指定端口的绑定
127.0.0.1:8080/path/.. # ip地址+端口+路径,当然这种写法也只会在开发环境下存在
  • 为了方便理解,按照我们假设的存储方式,三种Url对应的cookie被存储在cookies数据表中:
name value domain path other_info
非sessionid 非sessionvalue www.test.com:8080 path 其他信息
非sessionid 非sessionvalue 127.0.0.1:8080 path 其他信息
非sessionid 非sessionvalue www.test.com path 其他信息
sessionid 1234 www.test.com path 其他信息
  • 同理,浏览器从cookie中解析出目标URL对应sessionid的过程,我们可以简单理解为对数据表的查询。假设,我们访问 url:http://www.test.com/path/../.., select 语句如下:
select name , value 
from cookies 
where domain='www.test.com' and path='path'
  • 查询结果如下:
name value domain path other_info
非sessionid 非sessionvalue www.test.com path 其他信息
sessionid 1234 www.test.com path 其他信息
  • 我们很清楚,只有name = 'sessionid'的那条cookie才是我们想要的 存储sessionid的cookie,这步筛选过程,当然 只会在服务端发生。此时request请求头内容如下:
Request Headers
Cookie:sessionid=1234; 非sessionid=非sessionid

注意

  • 上述例子中,cookie中包含中文信息,实际使用,中文信息需要编码/解码
//发送cookie
Cookie cookie = new Cookie(URLEncoder.encode("非sessionid")
                          ,URLEncoder.encode("非sessionvalue"));
cookie.setComment(URLEncoder.encode("其他信息"));
response.addCookie(cookie);

//获得cookie中文内容
URLDecoder.decoder(request.getCookie().getName);//获取name
URLDecoder.decoder(request.getCookie().getValue);//获取value

强调

CookieDomainPath属性,是根据url解析出对应cookie的充分必要条件

  • setDomain(String urlPattern); //尽管服务端开放了操作Domain属性的方法,但是一般情况下,浏览器会自动重写该属性,所以服务端的设置通常是无效的。
  • setPath(String path); //服务端可以对Path进行设置,不会被浏览器复写,通常有效。

    • 手动设置
    Cookie sessionCookie = new Cookie("sessionid","1234");
    sessionCookie.setPath("/path");
    • 传统Spring项目,修改tomcatserver.xml<Context path="" />
    <Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true">
      <Context docBase="kuaiban-platform-service" path="/kuaiban-platform-service" />
      <!--这里path 即context-path ,指定了访问Web应用的Url入口-->
    </Host>
    • Spring Boot,可以直接配置application.properties/application.yml
    server.session.cookie.path=  # Path of the session cookie. default "/"

猜你喜欢

转载自blog.csdn.net/qq_32331073/article/details/80365871