Spring JWT 生成 Token

2022-08-07 09:19:54

Spring Jwt 生成 Token

由来

当前后端结合的时候可以根据请求返回数据,在服务端储存 cookie,session 等,但当前后端分离后,不光后端无法渲染前端,还会收到许多前端传来的请求,这时就需要 token 来验证用户信息。

Token

Token 是在服务端产生的。如果前端使用用户名/密码向服务端请求认证,服务端认证成功,那么在服务端会返回 Token 给前端。前端可以在每次请求的时候带上 Token 证明自己的合法地位。如果这个 Token 在服务端持久化(比如存入数据库),那它就是一个永久的身份令牌。
为防止密码等信息的泄露,常常是前端只传递 Token 除登陆等少量操作不会传递有关用户信息的内容,而 Token 也可以时常更新,以保证安全性。

JWT

在 java 中 JWT 便是生成 Token 的非常方便的工具。
可以用来验证用户身份以及对路由,服务和资源的访问权限进行验证。

结构

JWT是由三段信息构成的,例如:
eyJhbGciOiJIUzI1NiJ9.
eyJqdGkiOiJjOTRmMTYyNy00MzMxLTQzZmMtYWY4My1iNmM5ZTA1M2UzNTIiLCJpYXQiOjE1NjcwODQ1MzUsInN1YiI6InN5c3RlbSIsImlzcyI6Im5weSIsInVzZXJJZCI6MTM4OSwidXNlcm5hbWUiOiIxMSIsImV4cCI6MTU2NzE5MjUzNX0.
hUssKQEWZwg59tCls7FseXtvkde6XQ44FVSM1R437Rw

Header

JWT的头部承载两部分信息:token类型和采用的加密算法。
{
“alg”: “HS256”,
“typ”: “JWT”
}
声明加密的算法:有许多种,选择自己想要的就好,一般编程软件会有提示

Payload

载荷就是存放有效信息的地方。
有效信息包含三个部分

  1. 标准中注册的声明
  2. 公共的声明
  3. 私有的声明

标准中注册的声明 (建议但不强制使用) :
iss: JWT 签发者
sub: 面向的用户(JWT 所面向的用户)
aud: 接收 JWT 的一方
exp: 过期时间戳(jwt的过期时间,这个过期时间必须要大于签发时间)
nbf: 定义在什么时间之前,该 JWT 都是不可用的.
iat: jwt的签发时间
jti: jwt的唯一身份标识,主要用来作为一次性 Token,从而回避重放攻击。

secret

这个部分需要 base64 加密后的 header 和 base64 加密后的 payload 使用。连接组成的字符串,然后通过 header 中声明的加密方式进行加盐值 secret 组合加密,然后就构成了 JWT 的第三部分。
密钥secret是保存在服务端的,服务端会根据这个密钥进行生成token和进行验证,所以需要保护好。

依赖注入

如今常见的依赖有两种(本文以第二种为例):

<dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>3.4.0</version></dependency>
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.0</version></dependency>

代码实现

User类自己实现就好,简单的面向对象。

import io.jsonwebtoken.Claims;import io.jsonwebtoken.Jwts;import io.jsonwebtoken.SignatureAlgorithm;import java.util.Date;import java.util.HashMap;import java.util.Map;import java.util.UUID;publicclassJwtUtil{/**
     * 获取token
     * @param encryKey
     * @param minutes
     * @return
     */publicstatic StringgetToken(User user, String encryKey,long minutes){long currentTime= System.currentTimeMillis();//也可以直接传入 Map<String, Object> 做简单的修改即可
        Map<String, Object> map=newHashMap<>();
        map.put("userId", user.getId());return Jwts.builder().setId(UUID.randomUUID().toString())//当前用户.setIssuedAt(newDate())//签发日期.setSubject("system")//说明.setIssuer("npy")//签发者信息.signWith(SignatureAlgorithm.HS256, encryKey)//加密方式.addClaims(map).setExpiration(newDate(currentTime+ minutes*1000*60))//过期时间.compact();}/**
     * 验证是否到时间
     * @param token
     * @param encryKey
     * @return
     */publicstaticbooleanisExpiration(String token, String encryKey){try{long currentTime= System.currentTimeMillis();if(Jwts.parser().setSigningKey(encryKey).parseClaimsJws(token).getBody().getExpiration().after(newDate(currentTime))){returntrue;}else{returnfalse;}}catch(Exception e){returnfalse;}}/**
     * 获取claims
     * @param token
     * @param encryKey
     * @return
     */publicstatic ClaimsgetClamis(String token, String encryKey){try{
            Claims claims= Jwts.parser().setSigningKey(encryKey).parseClaimsJws(token).getBody();return claims;}catch(Exception e){return null;}}//    public static void main(String[] args) {//        String token =//"eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJjOTRmMTYyNy00MzMxLTQzZmMtYWY4My1iNmM5ZTA1M2UzNTIiLCJpYXQiOjE1NjcwODQ1MzUsInN1YiI6InN5c3RlbSIsImlzcyI6Im5weSIsInVzZXJJZCI6MTM4OSwidXNlcm5hbWUiOiIxMSIsImV4cCI6MTU2NzE5MjUzNX0.hUssKQEWZwg59tCls7FseXtvkde6XQ44FVSM1R437Rw";//        System.out.println(JwtUtil.getClamis(token, "salt").get("userId"));//        System.out.println(JwtUtil.getClamis(token, "salt").get("username"));//    }}
  • 作者:幽影相随
  • 原文链接:https://blog.csdn.net/weixin_43820352/article/details/100186207
    更新时间:2022-08-07 09:19:54