拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Cookie、Session、Token、JWT 四大认证机制详解(Java 实战)

1. Cookie 详解1.1 定义Cookie 是服务器在 HTTP 响应头中通过Set-Cookie字段下发给浏览器的一小段文本数据浏览器会将其保存在本地并在后续请求中通过Cookie请求头自动携带回服务器。Cookie 本质上是 HTTP 协议的无状态特性下用于在客户端保存状态的一种机制。1.2 核心特性客户端存储数据保存在浏览器端服务器不占用内存。自动携带浏览器根据 Cookie 的Domain和Path属性自动决定是否在请求中携带对应 Cookie无需前端手动处理。可设置生命周期通过Expires/Max-Age属性控制持久化时间未设置则为会话级 Cookie浏览器关闭即失效。大小受限单个 Cookie 大小上限约 4KB单域名下数量有限各浏览器不同通常 20~50 个。可被 JS 读取默认情况下JavaScript 可通过document.cookie读取存在 XSS 窃取风险可通过HttpOnly属性禁止 JS 访问。1.3 常用属性属性作用Domain指定 Cookie 可发送到的域名Path限定 Cookie 生效的路径范围Expires/Max-Age设置过期时间Secure仅允许在 HTTPS 连接下传输HttpOnly禁止 JavaScript 访问防 XSSSameSite控制跨站请求是否携带防 CSRF1.4 Java 代码演示importjavax.servlet.http.Cookie;importjavax.servlet.http.HttpServletResponse;importorg.springframework.web.bind.annotation.*;RestControllerpublicclassCookieController{// 下发 CookieGetMapping(/set-cookie)publicStringsetCookie(HttpServletResponseresponse){CookiecookienewCookie(username,admin);cookie.setMaxAge(60*60*24);// 1 天cookie.setHttpOnly(true);// 防 XSScookie.setSecure(true);// 仅 HTTPScookie.setPath(/);response.addCookie(cookie);returnCookie 已下发;}// 读取 CookieGetMapping(/get-cookie)publicStringgetCookie(CookieValue(nameusername,defaultValueguest)Stringusername){return当前用户: username;}}2. Session 详解2.1 定义Session会话是服务器端为每个用户维护的一份独立状态数据。用户登录成功后服务器创建一条 Session 记录通常以 Session ID 为键并将 Session ID 通过 Cookie 下发给浏览器。后续请求携带该 ID服务器据此找到对应的 Session 数据。2.2 核心特性服务端存储数据保存在服务器内存、文件或 Redis 中客户端只持有 Session ID。状态保持服务器可以随时修改 Session 中的数据实现登录态、购物车等有状态业务。可主动失效服务器可随时删除 Session实现强制下线、踢人等功能。集群扩展困难多节点部署时请求漂移到不同节点会导致 Session 丢失需引入 Redis 等共享存储。占用服务器资源大量在线用户会消耗服务器内存。2.3 Java 代码演示Spring Boot Redis 共享 Sessionimportorg.springframework.web.bind.annotation.*;importjavax.servlet.http.HttpSession;RestControllerpublicclassSessionController{// 登录写入 SessionPostMapping(/login)publicStringlogin(RequestParamStringusername,RequestParamStringpassword,HttpSessionsession){if(admin.equals(username)123456.equals(password)){session.setAttribute(userId,1001);session.setAttribute(username,username);session.setMaxInactiveInterval(30*60);// 30 分钟过期return登录成功;}return账号或密码错误;}// 受保护接口读取 SessionGetMapping(/profile)publicStringprofile(HttpSessionsession){ObjectuserIdsession.getAttribute(userId);if(userIdnull){return未登录;}return用户ID: userId, 用户名: session.getAttribute(username);}// 退出销毁 SessionPostMapping(/logout)publicStringlogout(HttpSessionsession){session.invalidate();return已退出登录;}}2.4 Spring Boot 集成 Redis 共享 Session!-- pom.xml 依赖 --dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-data-redis/artifactId/dependencydependencygroupIdorg.springframework.session/groupIdartifactIdspring-session-data-redis/artifactId/dependency# application.ymlspring:redis:host:localhostport:6379session:store-type:redistimeout:30m3. Token 详解3.1 定义Token令牌是一种无状态认证凭证。用户登录成功后服务器对用户信息进行签名生成一串加密字符串返回给前端。前端在后续请求中通过Authorization请求头携带该 Token服务器验证签名合法后即放行无需在服务端保存任何会话状态。3.2 核心特性无状态服务器不保存 Token 信息天然支持水平扩展适合微服务架构。自包含用户身份、权限、过期时间等信息都封装在 Token 内部。跨域友好通过 Header 传递不受 Cookie 同源策略限制。不可主动失效Token 签发后在过期前无法强制作废除非引入黑名单机制。泄露风险Token 一旦被窃取攻击者可在有效期内冒用需配合 HTTPS 和短有效期使用。3.3 认证流程用户提交账号密码登录。服务器验证通过后用密钥对用户信息签名生成 Token。前端保存 TokenLocalStorage / 内存 / Cookie。前端请求时在Authorization: Bearer token中携带。后端中间件校验签名和有效期通过则放行。3.4 Java 代码演示使用 jjwt 库!-- pom.xml 依赖 --dependencygroupIdio.jsonwebtoken/groupIdartifactIdjjwt-api/artifactIdversion0.11.5/version/dependencydependencygroupIdio.jsonwebtoken/groupIdartifactIdjjwt-impl/artifactIdversion0.11.5/versionscoperuntime/scope/dependencydependencygroupIdio.jsonwebtoken/groupIdartifactIdjjwt-jackson/artifactIdversion0.11.5/versionscoperuntime/scope/dependencyimportio.jsonwebtoken.*;importio.jsonwebtoken.security.Keys;importjavax.crypto.SecretKey;importjava.nio.charset.StandardCharsets;importjava.util.Date;publicclassJwtUtil{// 生产环境务必从环境变量读取严禁硬编码privatestaticfinalStringSECRETSystem.getenv(JWT_SECRET)!null?System.getenv(JWT_SECRET):change-this-to-a-very-long-random-secret-key-2026;privatestaticfinalSecretKeyKEYKeys.hmacShaKeyFor(SECRET.getBytes(StandardCharsets.UTF_8));privatestaticfinallongEXPIRE_MS2*60*60*1000;// 2 小时// 生成 TokenpublicstaticStringgenerateToken(LonguserId,Stringusername,Stringrole){returnJwts.builder().setSubject(String.valueOf(userId)).claim(username,username).claim(role,role).setIssuedAt(newDate()).setExpiration(newDate(System.currentTimeMillis()EXPIRE_MS)).signWith(KEY,SignatureAlgorithm.HS256).compact();}// 解析 TokenpublicstaticClaimsparseToken(Stringtoken){returnJwts.parserBuilder().setSigningKey(KEY).build().parseClaimsJws(token).getBody();}}importorg.springframework.web.bind.annotation.*;importio.jsonwebtoken.Claims;RestControllerpublicclassTokenController{PostMapping(/token-login)publicStringlogin(RequestParamStringusername,RequestParamStringpassword){if(admin.equals(username)123456.equals(password)){StringtokenJwtUtil.generateToken(1001L,username,ADMIN);return登录成功Token: token;}return账号或密码错误;}GetMapping(/token-profile)publicStringprofile(RequestHeader(Authorization)StringauthHeader){StringtokenauthHeader.replace(Bearer ,);ClaimsclaimsJwtUtil.parseToken(token);return用户ID: claims.getSubject(), 用户名: claims.get(username), 角色: claims.get(role);}}4. JWT 详解4.1 定义JWTJSON Web Token是目前最主流的 Token 实现标准RFC 7519。它由三部分组成用点号分隔Header.Payload.Signature各部分均经过 Base64Url 编码。4.2 结构解析部分内容说明Header{alg:HS256,typ:JWT}声明签名算法和令牌类型Payload{sub:1001,username:admin,exp:...}存放用户数据仅 Base64 编码未加密Signature对 Header Payload 用密钥做 HMAC-SHA256 的结果防止数据被篡改4.3 核心特性自包含用户信息直接编码在 Token 中服务器无需查库即可识别身份。防篡改签名保证任何对 Header 或 Payload 的修改都会导致校验失败。非加密Payload 只是 Base64 编码任何人可解码查看严禁存放密码等敏感信息。无状态服务器不保存 JWT适合分布式和微服务场景。不可撤销签发后无法在过期前主动失效需配合黑名单或短有效期。4.4 Java 代码演示完整生成与校验importio.jsonwebtoken.*;importio.jsonwebtoken.security.Keys;importjavax.crypto.SecretKey;importjava.nio.charset.StandardCharsets;importjava.util.Date;publicclassJwtService{privatefinalSecretKeykey;privatefinallongexpireMs;publicJwtService(Stringsecret,longexpireMs){this.keyKeys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8));this.expireMsexpireMs;}// 生成 JWTpublicStringcreateToken(LonguserId,Stringrole){DatenownewDate();returnJwts.builder().setSubject(String.valueOf(userId)).claim(role,role).setIssuedAt(now).setExpiration(newDate(now.getTime()expireMs)).signWith(key,SignatureAlgorithm.HS256).compact();}// 校验 JWT返回 Claims失败抛出异常publicClaimsverifyToken(Stringtoken)throwsJwtException{returnJwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token).getBody();}}importorg.springframework.web.bind.annotation.*;importio.jsonwebtoken.Claims;RestControllerpublicclassJwtController{privatefinalJwtServicejwtServicenewJwtService(System.getenv().getOrDefault(JWT_SECRET,a-very-long-random-secret-key-2026),2*60*60*1000L);PostMapping(/jwt-login)publicStringlogin(RequestParamStringusername,RequestParamStringpassword){if(admin.equals(username)123456.equals(password)){returnjwtService.createToken(1001L,ADMIN);}return账号或密码错误;}GetMapping(/jwt-profile)publicStringprofile(RequestHeader(Authorization)StringauthHeader){try{StringtokenauthHeader.replace(Bearer ,);ClaimsclaimsjwtService.verifyToken(token);return用户ID: claims.getSubject(), 角色: claims.get(role);}catch(ExpiredJwtExceptione){returnToken 已过期;}catch(JwtExceptione){return非法 Token;}}}4.5 Spring Boot 全局 JWT 拦截器importorg.springframework.web.servlet.HandlerInterceptor;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;importio.jsonwebtoken.Claims;publicclassJwtInterceptorimplementsHandlerInterceptor{privatefinalJwtServicejwtService;publicJwtInterceptor(JwtServicejwtService){this.jwtServicejwtService;}OverridepublicbooleanpreHandle(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler)throwsException{// 放行登录接口if(request.getRequestURI().contains(/login)){returntrue;}StringauthHeaderrequest.getHeader(Authorization);if(authHeadernull||!authHeader.startsWith(Bearer )){response.setStatus(401);response.getWriter().write(缺少凭证);returnfalse;}try{ClaimsclaimsjwtService.verifyToken(authHeader.replace(Bearer ,));request.setAttribute(userId,claims.getSubject());request.setAttribute(role,claims.get(role));returntrue;}catch(Exceptione){response.setStatus(401);response.getWriter().write(凭证无效或已过期);returnfalse;}}}5. 四种机制对比表对比维度CookieSessionTokenJWT存储位置客户端浏览器服务端内存/Redis客户端客户端是否无状态否否是是服务器存储压力无大无无可主动失效可设置过期可删除 Session不可不可水平扩展天然支持需共享存储Redis天然支持天然支持跨域支持受限需 CORS 配置受限需 CORS 配置友好Header 传递友好Header 传递安全性有 XSS/CSRF 风险相对安全数据在服务端依赖密钥和传输安全依赖密钥和传输安全数据可见性明文可见服务端可见可解码可见可解码可见未加密典型场景会话标识、偏好设置单体应用登录态移动端/API 认证微服务/分布式认证6. 总结Cookie、Session、Token、JWT 是四种层层递进的认证方案核心区别在于状态保存在哪里Cookie是客户端存储的载体本身不保存登录态只负责携带 Session ID 或 Token。Session把状态放在服务端安全可控但难以水平扩展适合单体应用。Token把状态封装到客户端令牌中实现无状态认证适合分布式架构。JWT是 Token 的标准实现自包含、防篡改但 Payload 未加密且不可主动失效。选型建议单体后台管理系统优先选 Session Redis微服务、高并发 API 优先选 JWT对安全极度敏感的场景可采用 JWT 短有效期 黑名单的混合方案。无论选择哪种HTTPS 传输、密钥安全管理和合理的过期策略都是必须坚守的底线。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门