Token,Session,Cookie,JWT,Oauth2傻傻分不清楚
前言
最近發現有些小伙伴,對Token、Session、Cookie、JWT、OAuth2這些概念非常容易搞混。
有些小伙伴在工作中可能會遇到過這樣的困惑:
- 做登錄功能時,到底該用Session還是JWT?
- OAuth2和Token是什么關系?
- 為什么有的方案要把Token存在Cookie里?
今天這篇文章專門跟大家一起聊聊這個話題,希望對你會有所幫助。
一、從餐廳就餐模型開始講
為了讓大家更好理解,我先用一個餐廳就餐的比喻來解釋這些概念:

現在,讓我們深入每個概念的技術細節。
二、Cookie:HTTP的世界身份證
2.1 什么是Cookie?
Cookie是存儲在瀏覽器端的一小段文本數據,由服務器通過HTTP響應頭的Set-Cookie字段發送給瀏覽器,瀏覽器隨后會自動在每次請求中通過Cookie頭將其帶回給服務器。
工作原理:

2.2 Cookie實戰代碼
// 服務器設置Cookie
@PostMapping("/login")
public ResponseEntity login(@RequestBody User user, HttpServletResponse response) {
if (authService.authenticate(user)) {
Cookie cookie = new Cookie("session_id", generateSessionId());
cookie.setMaxAge(3600); // 1小時有效期
cookie.setHttpOnly(true); // 防止XSS攻擊
cookie.setSecure(true); // 僅HTTPS傳輸
cookie.setPath("/"); // 對整個站點有效
response.addCookie(cookie);
return ResponseEntity.ok().build();
}
return ResponseEntity.status(401).build();
}
// 讀取Cookie
@GetMapping("/profile")
public ResponseEntity getProfile(@CookieValue("session_id") String sessionId) {
User user = sessionService.getUserBySession(sessionId);
return ResponseEntity.ok(user);
}
2.3 Cookie的重要屬性
| 屬性 | 作用 | 安全建議 |
|---|---|---|
| HttpOnly | 防止JavaScript訪問 | 必須設置為true,防XSS |
| Secure | 僅通過HTTPS傳輸 | 生產環境必須設置為true |
| SameSite | 控制跨站請求時是否發送Cookie | 建議設置為Strict或Lax |
| Max-Age | 設置Cookie有效期 | 根據業務安全性要求設置 |
三、Session:服務端的用戶檔案
3.1 什么是Session?
Session是存儲在服務器端的用戶狀態信息。服務器為每個用戶創建一個唯一的Session ID,并通過Cookie將這個ID傳遞給瀏覽器,瀏覽器后續請求時帶上這個ID,服務器就能識別用戶身份。
Session存儲結構:
// 典型的Session數據結構
public class UserSession {
private String sessionId;
private String userId;
private String username;
private Date loginTime;
private Date lastAccessTime;
private Map<String, Object> attributes; // 自定義屬性
// 省略getter/setter
}
3.2 Session實戰代碼
// 基于Spring Session的實現
@PostMapping("/login")
public String login(@RequestParam String username,
@RequestParam String password,
HttpSession session) {
User user = userService.authenticate(username, password);
if (user != null) {
// 將用戶信息存入Session
session.setAttribute("currentUser", user);
session.setAttribute("loginTime", new Date());
return "redirect:/dashboard";
}
return "login?error=true";
}
@GetMapping("/dashboard")
public String dashboard(HttpSession session) {
// 從Session獲取用戶信息
User user = (User) session.getAttribute("currentUser");
if (user == null) {
return "redirect:/login";
}
return "dashboard";
}
3.3 Session的存儲方案
1. 內存存儲(默認)
# application.yml
server:
servlet:
session:
timeout: 1800 # 30分鐘過期時間
2. Redis分布式存儲
@Configuration
@EnableRedisHttpSession // 啟用Redis Session存儲
public class SessionConfig {
@Bean
public LettuceConnectionFactory connectionFactory() {
return new LettuceConnectionFactory();
}
}
3. Session集群同步問題

四、Token:去中心化的身份令牌
4.1 什么是Token?
Token是一種自包含的身份憑證,服務器不需要在服務端存儲會話狀態,所有必要信息都包含在Token本身中。
Token vs Session 核心區別:

4.2 Token實戰代碼
// 生成Token
public String generateToken(User user) {
long currentTime = System.currentTimeMillis();
return JWT.create()
.withIssuer("myapp") // 簽發者
.withSubject(user.getId()) // 用戶ID
.withClaim("username", user.getUsername())
.withClaim("role", user.getRole())
.withIssuedAt(new Date(currentTime)) // 簽發時間
.withExpiresAt(new Date(currentTime + 3600000)) // 過期時間
.sign(Algorithm.HMAC256(secret)); // 簽名密鑰
}
// 驗證Token
public boolean validateToken(String token) {
try {
JWTVerifier verifier = JWT.require(Algorithm.HMAC256(secret))
.withIssuer("myapp")
.build();
DecodedJWT jwt = verifier.verify(token);
return true;
} catch (JWTVerificationException exception) {
return false;
}
}
五、JWT:現代化的Token標準
5.1 什么是JWT?
JWT(JSON Web Token)是一種開放標準(RFC 7519),用于在各方之間安全地傳輸信息作為JSON對象。
這種信息可以被驗證和信任,因為它是數字簽名的。
JWT結構:
header.payload.signature
解碼示例:
// Header
{
"alg": "HS256",
"typ": "JWT"
}
// Payload
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022,
"exp": 1516242622
}
// Signature
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
5.2 JWT實戰代碼
// 創建JWT
public String createJWT(User user) {
return Jwts.builder()
.setHeaderParam("typ", "JWT")
.setSubject(user.getId())
.setIssuer("myapp")
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + 3600000))
.claim("username", user.getUsername())
.claim("role", user.getRole())
.signWith(SignatureAlgorithm.HS256, secret.getBytes())
.compact();
}
// 解析JWT
public Claims parseJWT(String jwt) {
return Jwts.parser()
.setSigningKey(secret.getBytes())
.parseClaimsJws(jwt)
.getBody();
}
// 在Spring Security中使用JWT
@Component
public class JwtFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain) {
String token = resolveToken(request);
if (token != null && validateToken(token)) {
Authentication auth = getAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(auth);
}
chain.doFilter(request, response);
}
}
5.3 JWT的最佳實踐
1. 安全存儲
// 前端安全存儲方案
// 不推薦:localStorage(易受XSS攻擊)
// 推薦:HttpOnly Cookie(防XSS)或內存存儲
2. 令牌刷新機制
// 雙Token機制:Access Token + Refresh Token
public class TokenPair {
private String accessToken; // 短期有效:1小時
private String refreshToken; // 長期有效:7天
}
// 刷新令牌接口
@PostMapping("/refresh")
public ResponseEntity refresh(@RequestBody RefreshRequest request) {
String refreshToken = request.getRefreshToken();
if (validateRefreshToken(refreshToken)) {
String userId = extractUserId(refreshToken);
String newAccessToken = generateAccessToken(userId);
return ResponseEntity.ok(new TokenPair(newAccessToken, refreshToken));
}
return ResponseEntity.status(401).build();
}
六、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授權碼流程

6.3 OAuth 2.0實戰代碼
// Spring Security OAuth2配置
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("clientapp")
.secret(passwordEncoder.encode("123456"))
.authorizedGrantTypes("authorization_code", "refresh_token")
.scopes("read", "write")
.redirectUris("http://localhost:8080/callback");
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints.authenticationManager(authenticationManager)
.tokenStore(tokenStore())
.accessTokenConverter(accessTokenConverter());
}
}
// 資源服務器配置
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/api/public/**").permitAll()
.antMatchers("/api/private/**").authenticated()
.antMatchers("/api/admin/**").hasRole("ADMIN");
}
}
七、五大概念對比
為了讓大家更清晰地理解這五個概念的關系和區別,我準備了以下對比表格:
7.1 功能定位對比
| 概念 | 本質 | 存儲位置 | 主要用途 | 特點 |
|---|---|---|---|---|
| Cookie | HTTP狀態管理機制 | 瀏覽器 | 維持會話狀態 | 自動攜帶,有大小限制 |
| Session | 服務端會話信息 | 服務器 | 存儲用戶狀態 | 服務端狀態,需要存儲管理 |
| Token | 訪問憑證 | 客戶端/服務端 | 身份認證 | 自包含,可驗證 |
| JWT | Token的一種實現標準 | 客戶端/服務端 | 安全傳輸信息 | 標準化,自包含,可簽名 |
| 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

浙公網安備 33010602011771號