JWT主要是用于用户登录鉴权,传统的方法就是session认证。
http是无状态的协议,当有用户向系统使用账户名称和密码进行用户认证之后,下一次请求还要再一次用户认证才行。因为我们不能通过http协议知道是哪个用户发出的请求,所以如果要知道是哪个用户发出的请求,那就需要在服务器保存一份用户信息(保存至session),然后在认证成功后返回cookie值传递给浏览器,那么用户在下一次请求时就可以带上cookie值,服务器就可以识别是哪个用户发送的请求,是否已认证,是否登录过期等等。
session认证的缺点其实很明显,由于session是保存在服务器里,所以如果分布式部署应用的话,会出现session不能共享的问题,很难扩展。
JWT:Json Web Token 它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息。该信息可以被验证和信任,因为它是数字签名的。

流程:
用户信息是保存在客户端,关键在于生成JWT和解析JWT。
JWT一般是这样的字符串,分为三个部分,以"."隔开。
xxxxx.yyyyy.zzzzz
Header:第一部分是头部分,描述JWT元数据的Json对象
- {
- "alg": "HS256",
- "typ": "JWT"
- }
alg属性表示签名使用的算法,默认为HMAC SHA256(写为HS256),typ属性表示令牌的类型,JWT令牌统一写为JWT。最后,使用Base64 URL算法将上述JSON对象转换为字符串保存。
Payload:第二部分是Payload,也是一个Json对象,除了包含需要传递的数据,还有七个默认的字段供选择。
分别是,iss:发行人、exp:到期时间、sub:主题、aud:用户、nbf:在此之前不可用、iat:发布时间、jti:JWT ID用于标识该JWT。
如果自定义字段,可以这样定义:
- {
- //默认字段
- "sub":"主题123",
- //自定义字段
- "name":"java技术爱好者",
- "isAdmin":"true",
- "loginTime":"2021-12-05 12:00:03"
- }
JSON对象也使用Base64 URL算法转换为字符串保存。
Signature:第三部分是签名。是这样生成的,首先需要指定一个secret,该secret仅仅保存在服务器中,保证不能让其他用户知道。然后使用Header指定的算法对Header和Payload进行计算,然后就得出一个签名哈希。
JWT的优点:
导入依赖
- <dependency>
- <groupId>io.jsonwebtoken</groupId>
- <artifactId>jjwt</artifactId>
- <version>0.9.1</version>
- </dependency>
创建工具类,用于创建jwt字符串和解析jwt
-
- import io.jsonwebtoken.Claims;
- import io.jsonwebtoken.JwtBuilder;
- import io.jsonwebtoken.Jwts;
-
- import java.util.Date;
-
- /**
- *
- * @description JWT:令牌token生成
- */
- public class TokenUtil {
-
- // token有效期
- private static final long EXPIRATION = 86400L;//1day = 86400L
-
- /**
- *
- * @description 创建token工具方法
- */
- public static String createToken(User user) {
- JwtBuilder builder = Jwts.builder();
- builder.setAudience(user.getUserCode()) // 这个user.getUserCode()是我后续需要的参数
- .setIssuer("xxx")
- .claim("userId", user.getId()) // userId 是我自己后续需要的参数,这个根据自己的需求进行设置
- .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION * 1000));
- String accessToken = builder.compact();
- return accessToken;
- }
-
- /**
- *
- * @description 验证token返回用户code
- */
- public static String validateToken(String token) {
- Claims claims = Jwts.parserBuilder().build().parseClaimsJwt(token).getBody();
- String userCode = claims.getAudience();
- return userCode;
- }
-
- /**
- *
- * @description 验证token返回用户ID
- */
- public static String getUserIdFromToken(String token) {
- Claims claims = Jwts.parserBuilder().build().parseClaimsJwt(token).getBody();
- String userId = claims.get("userId", String.class);
- return userId;
- }
- }
有些微修改,我这里没有使用到第三部分。
链接:https://www.zhihu.com/question/485758060/answer/2257869896