一种身份认证技术-JWT
|
admin
2025年12月14日 16:33
本文热度 812
|
自从搭建Fudy Shop网站以来,一直用了基于session的身份认证。借助http session和分布式缓存可以将用户信息在任意的应用中进行传递。用户的信息统一由负责会员的核心应用负责,其他应用如果要获取用户信息,需要通过dubbo调用会员服务。最近在将服务统一收口到网关的时候,出现了些问题,在咨询了AI后,了解到JWT可能更适合我的应用场景。JWT我第一次接触大概是2017年的时候,知道它是一种身份认证的技术,不过之前我没做过类似项目,没有用过。于是今天借着机会,先了解下什么是JWT,怎么使用JWT,看它适不适合Fudy Shop网站开发的场景。 JWT的全称是JSON Web Token,是一种开放标准(RFC 7519)。它用于在各方之间以 JSON 对象安全地传输信息。它在网站开发中被广泛用作身份认证机制,特别是在前后端分离的架构中。 一个完整的 JWT 由三部分组成,用点号 `.` 连接,结构为 `header.payload.signature`比如下面这个就是一个完整的JWT,我用不同颜色标出了3个不同部分:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
1.Header(头部)
作用:描述令牌的元数据和签名算法
结构:
{ "alg": "HS256", "typ": "JWT" }
编码后:Base64Url 编码
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
2.Payload(载荷)
作用:这是 JWT 的核心,用于存储实际的声明(Claims)。声明分为三类:注册声明(如 `iss`, `exp`, `sub`)、公共声明和私有声明(自定义)。这部分信息同样会被 Base64Url 编码,构成 JWT 的第二部分。
声明类型:
注册声明(标准字段):
{ "iss": "issuer", "sub": "subject", "aud": "audience", "exp": 1710000000, "nbf": 1709990000, "iat": 1709980000, "jti": "unique-id" }
公共声明:自定义但建议注册的字段
私有声明:业务自定义字段
{ "userId": "12345", "username": "john_doe", "roles": ["user", "admin"]}
编码后:Base64Url 编码
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
3.Signature(签名)
作用:验证令牌的完整性和真实性
生成方式:
String signature = HMAC_SHA256.encode( base64UrlEncode(header) + "." + base64UrlEncode(payload), "your-secret-key");
我这里用java举例说明了下,签名,其实是对header,payload,执行jwt指定的算法进行计算,生成signature。因为包含的secret-key只有后端服务知道,所以前端无法仿造。我这猜想了下,服务端应该是在收到前端header中的JWT的时候,可以拿到header和payload,再给出自己的secret-key对这2个进行HMAC_SHA26计算,如果结果和传递过来的signature一致,就认为是对的。Header: {"alg":"HS256","typ":"JWT"}Payload: {"sub":"1234567890","name":"John Doe","iat":1516239022}
String header = base64UrlEncode(headerJson); String payload = base64UrlEncode(payloadJson);
String signature = HMACSHA256(header + "." + payload, "secret");
String jwt = header + "." + payload + "." + signature;
JWT 的身份认证流程简洁高效,主要分为认证、签发和验证三个步骤 认证是发生在用户登录阶段。用户打开登录页面,输入用户名,密码,点击登录按钮。服务端根据去数据库中获取相关数据,来判断用户的信息对不对。这个之前Fudy Shop里也是这么做的。这个阶段应该和session方式差不多。 JWT是在签发阶段生成的。之前的session方式,在对用户登录信息进行认证后,会将用户信息通过redis缓存存储到session中,接下来用户访问接口,都是从session中获取数据的来进行鉴权的。JWT则是无状态的,它不将数据进行存储,而是直接返回给客户端。 客户端在签发阶段收到JWT后,将JWT存储在前端。之后每次要调用需要鉴权的接口的时候,都将JWT带给服务端,这个 Token 放在 HTTP 请求头中,通常是 Authorization: Bearer <token> 以下是服务端验证签名的java代码示例,先解析jwt的3个部分。public boolean verifyJWT(String jwt, String secretKey) { try { String[] parts = jwt.split("\\."); if (parts.length != 3) { throw new IllegalArgumentException("Invalid JWT format"); }
String headerBase64 = parts[0]; String payloadBase64 = parts[1]; String signature = parts[2];
} catch (Exception e) { return false; }}
public boolean verifySignature(String headerBase64, String payloadBase64, String receivedSignature, String secretKey) {
String data = headerBase64 + "." + payloadBase64; String expectedSignature = HMACSHA256(data, secretKey);
return MessageDigest.isEqual( expectedSignature.getBytes(StandardCharsets.UTF_8), receivedSignature.getBytes(StandardCharsets.UTF_8) );}
看到这,应该对JWT是什么,如何使用已经有大概的了解了。项目中要使用的话,可能不需要写上面的代码,Java中已经提供了一些第三方库来处理,这个后面我评估下是否要将JWT集成到Fudy Shop网站中,替换之前的session版。
阅读原文:原文链接
该文章在 2025/12/15 9:41:48 编辑过