session和cookies关系和原理

前言

前几天思考了一下session跟cookies的关系和原理 发现以前对session跟cookies的理解一直都有误 以前我一直以为session是存在服务端 cookies存在客户端 他们的键值对是一一对应关系的 后来想了想 这其实是不完全对的


session和cookies的位置

之前我们说到我们需要一种跟踪和认证客户端的机制 这种机制在客户端处表现为cookies

cookies可以保存在浏览器缓存 磁盘中等等

这种机制在服务端表现为session

session可以保存在内存 缓存 memcache redis或者磁盘中等等

这些都是没问题的


cookies和session的对应关系

cookies和session上的键值对其实不是一一对应关系的 甚至可以说关系不大
我们使用java的servlet来举例子 就可以比较清楚的说明他们的关系

在我们服务端这边cookies和session不是一回事 而且它们都可以被我们服务端分别进行操作


设置cookies

在java servlet中 给http response增加一个键值对 {“login”; “mylogin”}

1
2
3
4
5
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
// add cookies
Cookie login = new Cookie("login", "mylogin");
resp.addCookie(login);
}

客户端那边的效果 成功设置这个键值对到cookies中
image_1cg8recrtgbg1m201gvdvu29q39.png-3.3kB

cookies原理
image_1cg8s7r6mdbe7mf1pd51kqu2vv1g.png-18.1kB


设置session

然后我给session对象设置一个键值对 在java servlet中给session设置键值对叫做setAttribute 设置键值对{“login”: “this is my login session”}

1
2
3
4
5
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
// add session attribute
HttpSession session = req.getSession();
session.setAttribute("login", "this is my login session");
}

然后我们在客户端的http response的cookies中发现新增了以下这个键值对
image_1cg8rn4b81fcg80l1epc1h181corm.png-4.8kB

只是新建了一个key为jsessionid的键值对 跟我们设置的session attribute毫无关系

其实事实是
服务端这边是很节省资源的 它不是建立TCP连接之后就直接给客户端简历一个session 而是执行到如下语句

1
HttpSession session = req.getSession();

这时候才给客户端新建一个session对象(如果没有session则新建一个session 如果有则返回) 这个session对象含有一个attribute map一个映射表来存储我们给session设置的一些键值对 当我们set attribute之后 这些键值对存在attribute map之中 并且会http response新建一个特别的键值对

这个键值对就是我们上面看到的那个跟我们设置的session attribute毫无关系的cookies键值对

image_1cg8rn4b81fcg80l1epc1h181corm.png-4.8kB
这个jsessionid的cookies值顾名思义就是在cookies中用来标记这个客户端属于哪个session的唯一属性

所以说我们设置的所有session attribute都是存在服务端的本地的 给客户端那边传送过去关于session那部分的内容仅仅只是一个用来标识客户端所属session的session id 而session的所有内容都是存在服务端本地 之后对于每次客户端的请求 服务端都可以根据它请求头的session id这个cookie值(名字因所用框架有别 上面使用servlet 是jsessionid)来证明它是那个session的 然后根据这个session id在内存缓存memcache或者redis中找到这个session 继而找到这个session用来存键值对(就是attributes)的attribute map 从而找到我们在session中设置的内容

所以说cookies和session的内容 本质上除了需要在cookies上设置一个session id的cookies值来标记客户端所属session 其他基本毫无关系的 更不存在以前理解的一一对应关系

session原理
image_1cg8u36631o2ft241indpi019qj2a.png-39.6kB

综上所述

  • cookies是一种存储在客户端的 对客户端进行跟踪和认证的机制
  • session是一种存储在服务端的 对客户端进行跟踪和认证的机制 session的设置需要给cookies设置一个特殊的sessionid字段值
  • 对于服务端开发者来说 这两种机制都是可选的 并且是可以结合使用的 但是他们之间不是一回事