Cookie、Session和JWT

从客户端与服务器建立HTTP连接到断开连接的过程,称为一个会话。一个会话可以包含多次请求与响应。

由于HTTP协议是无状态的,服务器无法区分前后两个请求是否来自同一设备,因此有了三种会话跟踪方案:CookieSessionJWT

存储在浏览器中,发起请求时浏览器会自动带上Cookie,收到响应时浏览器会自动存储Cookie,是HTTP协议自带的功能。

Cookie的缺点:

  1. 只有浏览器支持Cookie,APP不支持
  2. 不安全,存在CSRF攻击,且用户可以禁用Cookie
  3. 不能跨域

代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Slf4j
@RestController
public class CookieController {

@GetMapping("/cookie1")
public Result cookie1(HttpServletResponse response) {
response.addCookie(new Cookie("key", "value"));
return Result.ok();
}

@GetMapping("/cookie2")
public Result cookie2(HttpServletRequest request) {
Cookie[] cookies = request.getCookies();
for (Cookie cookie : cookies) {
if (cookie.getName().equals("key")) {
log.debug(cookie.getValue());
}
}
return Result.ok();
}
}

Session

Session是服务器在每个HTTP连接中对应的会话对象。Session存储在服务器中,其底层是基于Cookie实现的。

在建立连接第一次请求时,服务器会创建一个Session,每一次请求服务器都可以获取到其Session。每个Session有一个id,服务器响应数据时,会将Session的id放在Cookie中响应给浏览器。浏览器每次请求时会在Cookie中带上Session的id,服务器再根据id找到对应的Session,从而分辨前后两次请求是否是同一会话。

Session的优点:

  1. 存储在服务端,安全

缺点:

  1. 在服务器集群环境下无法直接使用,不同服务器Session不一致
  2. Cookie的缺点它也有

代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Slf4j
@RestController
public class SessionController {

@GetMapping("/session1")
public Result session1(HttpSession session) {
session.setAttribute("key", "value");
return Result.ok();
}

@GetMapping("/session2")
public Result session2(HttpServletRequest request) {
HttpSession session = request.getSession();
log.info(session.getAttribute("key").toString());
return Result.ok();
}
}

JWT