springboot-jwt鉴权方案

54 阅读1分钟

springboot-jwt鉴权方案

引入相关库

<!--   maven - pom.xml    -->
<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.4.1</version>
</dependency>

配置jwt

jwt:
  header: "Authorization"     # token 返回头部
  tokenPrefix: "Bearer "      # token 前缀
  secret: "dasu23154c2d" # 私钥
  expireTime: 43200            # token 的有效时间

新建jwt工具类,错误类的抛出最好使用自己自定义错误类

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.Verification;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.Date;

@Component
@ConfigurationProperties(prefix = "jwt")
public class JwtUtil {
    /**
     * 定义 token 返回头部
     */
    public static String header;

    /**
     * token 前缀
     */
    public static String tokenPrefix;

    /**
     * 签名密钥
     */
    public static String secret;

    /**
     * 有效期
     */
    public static long expireTime;

    /**
     * 存进客户端的 token 的 key 名
     */
    public static final String USER_LOGIN_TOKEN = "token";

    /**
     * 设置 token 头部
     * @param header token 头部
     */
    public void setHeader(String header) {
        JwtUtil.header = header;
    }

    /**
     * 设置 token 前缀
     * @param tokenPrefix token 前缀
     */
    public void setTokenPrefix(String tokenPrefix) {
        JwtUtil.tokenPrefix = tokenPrefix;
    }

    /**
     * 设置 token 密钥
     * @param secret token 密钥
     */
    public void setSecret(String secret) {
        JwtUtil.secret = secret;
    }

    /**
     * 设置 token 有效时间
     * @param expireTimeInt token 有效时间
     */
    public void setExpireTime(int expireTimeInt) {
        JwtUtil.expireTime = expireTimeInt;
    }

    /**
     * 创建 TOKEN
     * JWT 构成: header, payload, signature
     * @param sub jwt 所面向的用户,即用户名
     * @return token 值
     */
    public static String createToken(String sub) {
        return tokenPrefix + JWT.create()
                .withSubject(sub)
                .withExpiresAt(new Date(System.currentTimeMillis() + expireTime))
                .sign(Algorithm.HMAC512(secret));
    }

    /**
     * 验证 token
     * @param token 验证的 token 值
     * @return 用户名
     */
    public static String validateToken(String token) {
        Verification verification = JWT.require(Algorithm.HMAC512(secret));
        JWTVerifier jwtVerifier = verification.build();
        // 去除 token 的前缀
        String noPrefixToken = token.replace(tokenPrefix, "");
        DecodedJWT decodedJwt = jwtVerifier.verify(noPrefixToken);
        if(decodedJwt != null) {
            return decodedJwt.getSubject();
        }
        return "";
    }

    /**
     * 检查 token 是否需要更新
     * @param token token 值
     * @return 过期时间
     */
    public static boolean isNeedUpdate(String token) throws Exception {
        // 获取 token 过期时间
        Date expiresAt = null;
        try {
            expiresAt = JWT.require(Algorithm.HMAC512(secret))
                    .build()
                    .verify(token.replace(tokenPrefix, ""))
                    .getExpiresAt();
        } catch (TokenExpiredException e){
            return true;
        } catch (Exception e){
            throw new Exception("token 验证失败");
        }
        // 需要更新
        return (expiresAt.getTime() - System.currentTimeMillis()) < (expireTime >> 1);
    }
}

具体使用

前端代码

// 请求时在 Authorization 中带上 code
headers: {
    Authorization: code
}

后端代码

String code = "需要加密内容";

// 加密
Strung sub = JwtUtil.createToken(code);

// 解密
String result = JwtUtil.validateToken(token);

// 错误类
//TokenExpiredException 验证码已过期

参考资料