找回密码
 立即注册
首页 业界区 业界 Token,Session,Cookie,JWT,Oauth2傻傻分不清楚

Token,Session,Cookie,JWT,Oauth2傻傻分不清楚

轩辕娅童 昨天 17:23
前言

最近发现有些小伙伴,对Token、Session、Cookie、JWT、OAuth2这些概念非常容易搞混。
有些小伙伴在工作中可能会遇到过这样的困惑:

  • 做登录功能时,到底该用Session还是JWT?
  • OAuth2和Token是什么关系?
  • 为什么有的方案要把Token存在Cookie里?
今天这篇文章专门跟大家一起聊聊这个话题,希望对你会有所帮助。
一、从餐厅就餐模型开始讲

为了让大家更好理解,我先用一个餐厅就餐的比喻来解释这些概念:
1.png

现在,让我们深入每个概念的技术细节。
二、Cookie:HTTP的世界身份证

2.1 什么是Cookie?

Cookie是存储在浏览器端的一小段文本数据,由服务器通过HTTP响应头的Set-Cookie字段发送给浏览器,浏览器随后会自动在每次请求中通过Cookie头将其带回给服务器。
工作原理
2.png

2.2 Cookie实战代码
  1. // 服务器设置Cookie
  2. @PostMapping("/login")
  3. public ResponseEntity login(@RequestBody User user, HttpServletResponse response) {
  4.     if (authService.authenticate(user)) {
  5.         Cookie cookie = new Cookie("session_id", generateSessionId());
  6.         cookie.setMaxAge(3600); // 1小时有效期
  7.         cookie.setHttpOnly(true); // 防止XSS攻击
  8.         cookie.setSecure(true); // 仅HTTPS传输
  9.         cookie.setPath("/"); // 对整个站点有效
  10.         response.addCookie(cookie);
  11.         return ResponseEntity.ok().build();
  12.     }
  13.     return ResponseEntity.status(401).build();
  14. }
  15. // 读取Cookie
  16. @GetMapping("/profile")
  17. public ResponseEntity getProfile(@CookieValue("session_id") String sessionId) {
  18.     User user = sessionService.getUserBySession(sessionId);
  19.     return ResponseEntity.ok(user);
  20. }
复制代码
2.3 Cookie的重要属性

属性作用安全建议HttpOnly防止JavaScript访问必须设置为true,防XSSSecure仅通过HTTPS传输生产环境必须设置为trueSameSite控制跨站请求时是否发送Cookie建议设置为Strict或LaxMax-Age设置Cookie有效期根据业务安全性要求设置三、Session:服务端的用户档案

3.1 什么是Session?

Session是存储在服务器端的用户状态信息。服务器为每个用户创建一个唯一的Session ID,并通过Cookie将这个ID传递给浏览器,浏览器后续请求时带上这个ID,服务器就能识别用户身份。
Session存储结构
  1. // 典型的Session数据结构
  2. public class UserSession {
  3.     private String sessionId;
  4.     private String userId;
  5.     private String username;
  6.     private Date loginTime;
  7.     private Date lastAccessTime;
  8.     private Map<String, Object> attributes; // 自定义属性
  9.    
  10.     // 省略getter/setter
  11. }
复制代码
3.2 Session实战代码
  1. // 基于Spring Session的实现
  2. @PostMapping("/login")
  3. public String login(@RequestParam String username,
  4.                    @RequestParam String password,
  5.                    HttpSession session) {
  6.     User user = userService.authenticate(username, password);
  7.     if (user != null) {
  8.         // 将用户信息存入Session
  9.         session.setAttribute("currentUser", user);
  10.         session.setAttribute("loginTime", new Date());
  11.         return "redirect:/dashboard";
  12.     }
  13.     return "login?error=true";
  14. }
  15. @GetMapping("/dashboard")
  16. public String dashboard(HttpSession session) {
  17.     // 从Session获取用户信息
  18.     User user = (User) session.getAttribute("currentUser");
  19.     if (user == null) {
  20.         return "redirect:/login";
  21.     }
  22.     return "dashboard";
  23. }
复制代码
3.3 Session的存储方案

1. 内存存储(默认)
  1. # application.yml
  2. server:
  3.   servlet:
  4.     session:
  5.       timeout: 1800 # 30分钟过期时间
复制代码
2. Redis分布式存储
  1. @Configuration
  2. @EnableRedisHttpSession // 启用Redis Session存储
  3. public class SessionConfig {
  4.     @Bean
  5.     public LettuceConnectionFactory connectionFactory() {
  6.         return new LettuceConnectionFactory();
  7.     }
  8. }
复制代码
3. Session集群同步问题
3.png

四、Token:去中心化的身份令牌

4.1 什么是Token?

Token是一种自包含的身份凭证,服务器不需要在服务端存储会话状态,所有必要信息都包含在Token本身中。
Token vs Session 核心区别
4.png

4.2 Token实战代码
  1. // 生成Token
  2. public String generateToken(User user) {
  3.     long currentTime = System.currentTimeMillis();
  4.     return JWT.create()
  5.             .withIssuer("myapp") // 签发者
  6.             .withSubject(user.getId()) // 用户ID
  7.             .withClaim("username", user.getUsername())
  8.             .withClaim("role", user.getRole())
  9.             .withIssuedAt(new Date(currentTime)) // 签发时间
  10.             .withExpiresAt(new Date(currentTime + 3600000)) // 过期时间
  11.             .sign(Algorithm.HMAC256(secret)); // 签名密钥
  12. }
  13. // 验证Token
  14. public boolean validateToken(String token) {
  15.     try {
  16.         JWTVerifier verifier = JWT.require(Algorithm.HMAC256(secret))
  17.                 .withIssuer("myapp")
  18.                 .build();
  19.         DecodedJWT jwt = verifier.verify(token);
  20.         return true;
  21.     } catch (JWTVerificationException exception) {
  22.         return false;
  23.     }
  24. }
复制代码
五、JWT:现代化的Token标准

5.1 什么是JWT?

JWT(JSON Web Token)是一种开放标准(RFC 7519),用于在各方之间安全地传输信息作为JSON对象。
这种信息可以被验证和信任,因为它是数字签名的。
JWT结构
  1. header.payload.signature
复制代码
解码示例
  1. // Header
  2. {
  3.   "alg": "HS256",
  4.   "typ": "JWT"
  5. }
  6. // Payload
  7. {
  8.   "sub": "1234567890",
  9.   "name": "John Doe",
  10.   "iat": 1516239022,
  11.   "exp": 1516242622
  12. }
  13. // Signature
  14. HMACSHA256(
  15.   base64UrlEncode(header) + "." +
  16.   base64UrlEncode(payload),
  17.   secret)
复制代码
5.2 JWT实战代码
  1. // 创建JWT
  2. public String createJWT(User user) {
  3.     return Jwts.builder()
  4.             .setHeaderParam("typ", "JWT")
  5.             .setSubject(user.getId())
  6.             .setIssuer("myapp")
  7.             .setIssuedAt(new Date())
  8.             .setExpiration(new Date(System.currentTimeMillis() + 3600000))
  9.             .claim("username", user.getUsername())
  10.             .claim("role", user.getRole())
  11.             .signWith(SignatureAlgorithm.HS256, secret.getBytes())
  12.             .compact();
  13. }
  14. // 解析JWT
  15. public Claims parseJWT(String jwt) {
  16.     return Jwts.parser()
  17.             .setSigningKey(secret.getBytes())
  18.             .parseClaimsJws(jwt)
  19.             .getBody();
  20. }
  21. // 在Spring Security中使用JWT
  22. @Component
  23. public class JwtFilter extends OncePerRequestFilter {
  24.     @Override
  25.     protected void doFilterInternal(HttpServletRequest request,
  26.                                   HttpServletResponse response,
  27.                                   FilterChain chain) {
  28.         String token = resolveToken(request);
  29.         if (token != null && validateToken(token)) {
  30.             Authentication auth = getAuthentication(token);
  31.             SecurityContextHolder.getContext().setAuthentication(auth);
  32.         }
  33.         chain.doFilter(request, response);
  34.     }
  35. }
复制代码
5.3 JWT的最佳实践

1. 安全存储
  1. // 前端安全存储方案
  2. // 不推荐:localStorage(易受XSS攻击)
  3. // 推荐:HttpOnly Cookie(防XSS)或内存存储
复制代码
2. 令牌刷新机制
  1. // 双Token机制:Access Token + Refresh Token
  2. public class TokenPair {
  3.     private String accessToken;  // 短期有效:1小时
  4.     private String refreshToken; // 长期有效:7天
  5. }
  6. // 刷新令牌接口
  7. @PostMapping("/refresh")
  8. public ResponseEntity refresh(@RequestBody RefreshRequest request) {
  9.     String refreshToken = request.getRefreshToken();
  10.     if (validateRefreshToken(refreshToken)) {
  11.         String userId = extractUserId(refreshToken);
  12.         String newAccessToken = generateAccessToken(userId);
  13.         return ResponseEntity.ok(new TokenPair(newAccessToken, refreshToken));
  14.     }
  15.     return ResponseEntity.status(401).build();
  16. }
复制代码
六、OAuth 2.0:授权框架之王

6.1 什么是OAuth 2.0?

OAuth 2.0是一个授权框架,允许第三方应用在获得用户授权后,代表用户访问受保护的资源。
OAuth 2.0角色

  • 资源所有者(Resource Owner):用户
  • 客户端(Client):第三方应用
  • 授权服务器(Authorization Server):颁发访问令牌
  • 资源服务器(Resource Server):托管受保护资源
6.2 OAuth 2.0授权码流程

5.png

6.3 OAuth 2.0实战代码
  1. // Spring Security OAuth2配置
  2. @Configuration
  3. @EnableAuthorizationServer
  4. public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
  5.    
  6.     @Autowired
  7.     private AuthenticationManager authenticationManager;
  8.    
  9.     @Override
  10.     public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
  11.         clients.inMemory()
  12.                 .withClient("clientapp")
  13.                 .secret(passwordEncoder.encode("123456"))
  14.                 .authorizedGrantTypes("authorization_code", "refresh_token")
  15.                 .scopes("read", "write")
  16.                 .redirectUris("http://localhost:8080/callback");
  17.     }
  18.    
  19.     @Override
  20.     public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
  21.         endpoints.authenticationManager(authenticationManager)
  22.                 .tokenStore(tokenStore())
  23.                 .accessTokenConverter(accessTokenConverter());
  24.     }
  25. }
  26. // 资源服务器配置
  27. @Configuration
  28. @EnableResourceServer
  29. public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
  30.    
  31.     @Override
  32.     public void configure(HttpSecurity http) throws Exception {
  33.         http.authorizeRequests()
  34.                 .antMatchers("/api/public/**").permitAll()
  35.                 .antMatchers("/api/private/**").authenticated()
  36.                 .antMatchers("/api/admin/**").hasRole("ADMIN");
  37.     }
  38. }
复制代码
七、五大概念对比

为了让大家更清晰地理解这五个概念的关系和区别,我准备了以下对比表格:
7.1 功能定位对比

概念本质存储位置主要用途特点CookieHTTP状态管理机制浏览器维持会话状态自动携带,有大小限制Session服务端会话信息服务器存储用户状态服务端状态,需要存储管理Token访问凭证客户端/服务端身份认证自包含,可验证JWTToken的一种实现标准客户端/服务端安全传输信息标准化,自包含,可签名OAuth2授权框架不直接存储第三方授权标准化授权流程7.2 应用场景对比

场景推荐方案原因说明传统Web应用Session + Cookie简单易用,生态成熟前后端分离应用JWT无状态,适合API认证第三方登录OAuth 2.0标准化授权,安全可靠微服务架构JWT分布式认证,无需会话同步移动端应用Token轻量级,适合移动网络7.3 安全考虑对比

安全威胁Cookie方案防护Token/JWT方案防护XSS攻击HttpOnly Cookie避免localStorage存储CSRF攻击SameSite Cookie自定义Header+CSRF Token令牌泄露短期有效+HTTPS短期有效+HTTPS+刷新机制数据篡改服务端验证签名验证总结

通过今天的深入探讨,我们可以得出以下结论:

  • Cookie是载体:HTTP协议的状态管理机制,是Session和Token的传输媒介之一。
  • Session是状态:服务端维护的会话状态,需要借助Cookie或URL重写来实现。
  • Token是凭证:认证授权的凭证,可以放在Cookie、Header或URL中。
  • JWT是标准:Token的一种标准化实现,自包含、可验证、可信任。
  • OAuth2是框架:授权框架,定义了完整的第三方授权流程。
最终建议

  • 简单Web应用:Session + Cookie
  • 前后端分离:JWT + HTTP Header
  • 第三方授权:OAuth 2.0 + JWT
没有最好的方案,只有最合适的方案。
理解每个技术的本质和适用场景,才能做出正确的架构决策。
最后说一句(求关注,别白嫖我)

如果这篇文章对您有所帮助,或者有所启发的话,帮忙关注一下我的同名公众号:苏三说技术,您的支持是我坚持写作最大的动力。
求一键三连:点赞、转发、在看。
关注公众号:【苏三说技术】,在公众号中回复:进大厂,可以免费获取我最近整理的10万字的面试宝典,好多小伙伴靠这个宝典拿到了多家大厂的offer。
本文收录于我的技术网站:http://www.susan.net.cn

来源:豆瓜网用户自行投稿发布,如果侵权,请联系站长删除

相关推荐

您需要登录后才可以回帖 登录 | 立即注册