【JavaWeb】Session 和 Cookie

  • 会话(Session):用户打开一个浏览器,访问了一些web资源,关闭浏览器,这个过程可以称为一个会话。
  • 有状态会话:浏览器能够保存客户端信息的会话。

保存会话

  • Cookie:客户端技术(请求,响应),服务器给客户端创建Cookie。是服务器通知客户端保存键值对的一种技术,客户端有了Cookie后,每次请求都会发送给服务器,每个Cookie的大小不能超过4kb
  • Session:服务器技术,可以保存用户的会话信息。可以把信息和数据放在session中

为什么需要保存会话?

因为 HTTP 连接是短连接,是无状态的。用户之前登陆过后再次登录时,还需要再次输入用户名和密码信息,因此为了帮用户保存这些信息,需要使用 Session 和 Cookie 技术(或 Token 技术)。

Session 原理

每个客户端(浏览器)在与服务器端产生连接后,都会在服务器端为该客户端创建一个独有的 Session 对象。Session 就是 Tomcat 服务器内存中保存的一个 Map 对象,所有 Session 对象都放到一个 SessionManager 里进行管理,不同的 Session 代表与不同的客户端进行的会话。

Session 和 Cookie 的关系:

  • 在某个客户端(浏览器)第一次访问服务器时,将创建一个 Session 对象,并保存到服务器端
  • 同时令客户端保存一个 jsessionid = sessionId 的 Cookie。其 key 值是固定的 jsessionid,value 是 sessionId。浏览器关闭前该 Cookie 将一直存在
  • Cookie 中还保存着一个重要信息:Domain(域名)。该值保存着该 Cookie 可以访问的网站域名。当访问一个网站时,浏览器会从目前存活的所有 Cookie 中选出 Domain 匹配当前网站的那些 Cookie,并在访问该网站时在请求头里带上这些 Cookie。
  • 之后 Cookie 存在期间每次访问对应 Domain 的服务器都将带上 Cookie 信息(在请求头中)
  • 浏览器关闭后,清除掉 Cookie,服务器端清除掉 Session

Cookie 是浏览器负责保存Session 是服务器负责保存。Cookie 中保存着 Session 信息,对应唯一的一个 Session。

示意图:

image-20220113161932370

Session 安全性

问题:如果黑客随意编写 Session ID,不就能登录任意用户的账号了吗?

加签验签可以解决该问题。

  • 加签:服务器在发送 Cookie 之前对这个含有 Session ID 的 Cookie 进行签名,生成一个签名 sign 一同发送给浏览器,也作为该域名下的一个 Cookie。
  • 验签:当浏览器再发送请求时,服务器会先验证该请求携带的 Cookie 中,签名 sign 能否匹配上 Session ID。如果能匹配,则认证成功;否则,认证失败,拒绝访问。

支付宝的支付服务同样有加签和验签步骤保证数据安全性。

服务器创建Cookie

image-20210505095556020

服务器获取客户端的Cookie

image-20210505100507884

  1. 从请求中拿到Cookie信息
  2. 服务器响应给客户端Cookie
1
2
3
4
5
6
7
8
9
Cookie[] cookies = req.getCookies(); // 获得cookies

cookie.getName(); // 获得cookie中的Key
cookie.getValue(); // 获得cookie中的Value

new Cookie("keyName", value); // 新建一个Cookie

cookie.setMaxAge(24*60*60); // 设置cookie的有效期,不设置默认关闭浏览器时删除
resp.addCookie(cookie); // 响应给客户端一个cookie

删除Cookie的方法:

  • 不设置有效期,关闭浏览器(关闭Session),自动失效;
  • 设置有效期,时间为0。

Cookie有效路径Path的设置:通过设置path路径可以过滤掉不符合路径的Cookie。

Session

服务器会给每一个用户(浏览器)创建一个Session对象。一个Session独占一个浏览器,只要浏览器没关,这个Session就一直存在。用户登录之后,整个网站都可以访问到用户信息。

Session技术,底层是基于Cookie技术实现的:每次创建出的Session对象都会保存成一个Cookie对象传给浏览器保存(该Cookie对象的生命周期为Session级别,即关闭浏览器后销毁)。

image-20210506103813937

Session和Cookie的区别:

  • Cookie是把用户的数据写给用户的浏览器,浏览器保存(可以保存多个)
  • Session是把用户的浏览器写到用户独占的Session中,服务器保存(保存重要的信息,减少资源的浪费)
  • Session对象由服务器创建

使用场景:

  • 保存一个登录用户的信息
  • 购物车信息
  • 在整个网站中经常用到的数据
1
2
3
4
5
6
7
8
9
10
11
12
// 在session中存入信息
HttpSession session = req.getSession();
session.setAttribute("name", "zhangsan");
String sessionId = session.getId();

// 从session中获取信息
HttpSession session = req.getSession();
String name = session.getAttribute("name");

// 注销session
session.removeAttribute("name");
session.invalidate();

Session销毁方法:

  1. 手动销毁:
1
getSession().invalidate();
  1. 自动销毁:设置会话自动过期:web.xml配置
1
2
3
4
<session-config>
<!-- 15分钟后过期 -->
<session-timeout>15</session-timeout>
</session-config>

分布式 Session

关于分布式 Session 的详细介绍见文章http://blog.yuyunzhao.cn/2021/12/20/%E3%80%90Spring%E3%80%91SpringSession/

JWT

如果某些客户端不支持 Cookie,那么上述方法也就失效了。并且基于 Session Cookie 方式的存储方法会对服务器造成一定的性能损耗。因此需要引入一种新的技术来解决存储问题:JWT。

关于 JWT 的介绍和使用见文章 【JavaWeb】JWT