jwt 工具类

该博客介绍了JWT(JSON Web Token)的使用,包括生成JWT载荷,设置标准字段如JWTID、签发者、过期时间等,并提供了JWT工具类用于生成和解析JWT。此外,还展示了如何在Spring框架中使用TransmittableThreadLocal进行JWT载荷的线程安全存储和获取,确保权限验证的安全性。
摘要由CSDN通过智能技术生成
import java.io.Serializable;
import java.util.Date;

/**
 * JWT载荷
 */
public class JwtPayload implements Serializable {
    private static final long serialVersionUID = -3034724392253728198L;

    public static final String USER_ID = "userId";
    public static final String INTERNAL = "internal";

    // ========================= JWT标准字段 =========================

    /**
     * JWT ID 唯一标识(UUID)
     */
    private String jti;

    /**
     * Issuer 签发者
     */
    private String iss;

    /**
     * Issuer at 签发时间(时间戳)
     */
    private Date iat;

    /**
     * Expire 过期时间(时间戳)
     */
    private Date exp;

    /**
     * Not Before 如果当前时间在此时间之前则token不被接受
     */
    private Date nbf;

    /**
     * Audience 接收方
     */
    private String aud;

    /**
     * Subject 面向的用户
     */
    private String sub;

    /**
     * 用户ID
     */
    private Long userId;

    /**
     * 是否为内置
     */
    private boolean internal;

    public String getJti() {
        return jti;
    }

    public void setJti(String jti) {
        this.jti = jti;
    }

    public String getIss() {
        return iss;
    }

    public void setIss(String iss) {
        this.iss = iss;
    }

    public Date getIat() {
        return iat;
    }

    public void setIat(Date iat) {
        this.iat = iat;
    }

    public Date getExp() {
        return exp;
    }

    public void setExp(Date exp) {
        this.exp = exp;
    }

    public Date getNbf() {
        return nbf;
    }

    public void setNbf(Date nbf) {
        this.nbf = nbf;
    }

    public String getAud() {
        return aud;
    }

    public void setAud(String aud) {
        this.aud = aud;
    }

    public String getSub() {
        return sub;
    }

    public void setSub(String sub) {
        this.sub = sub;
    }

    public Long getUserId() {
        return userId;
    }

    public void setUserId(Long userId) {
        this.userId = userId;
    }

    public boolean isInternal() {
        return internal;
    }

    public void setInternal(boolean internal) {
        this.internal = internal;
    }

    @Override
    public String toString() {
        return "JwtPayload{" +
                "jti='" + jti + '\'' +
                ", iss='" + iss + '\'' +
                ", iat=" + iat +
                ", exp=" + exp +
                ", nbf=" + nbf +
                ", aud='" + aud + '\'' +
                ", sub='" + sub + '\'' +
                ", userId=" + userId +
                ", internal=" + internal +
                '}';
    }
}
import io.jsonwebtoken.*;
import org.springframework.lang.NonNull;

/**
 * JWT工具类
 */
public class JwtUtils {

    /**
     * 生成 JWT
     *
     * @param payload JWT 载荷
     * @param secret  密钥
     * @return JWT字符串
     * @since 1.1.0.211021
     */
    @NonNull
    public static String generateJwt(@NonNull JwtPayload payload, @NonNull String secret) {
        return Jwts.builder()
                .setId(payload.getJti())
                .setIssuer(payload.getIss())
                .setIssuedAt(payload.getIat())
                .setExpiration(payload.getExp())
                .setNotBefore(payload.getNbf())
                .setAudience(payload.getAud())
                .setSubject(payload.getSub())
                .claim(JwtPayload.USER_ID, payload.getUserId())
                .claim(JwtPayload.INTERNAL, payload.isInternal())
                .signWith(SignatureAlgorithm.HS256, secret)
                .compact();
    }

    /**
     * 解析JwtToken
     *
     * @param token  JwtToken
     * @param secret 密钥
     * @return DecodedJWT字符串
     * @throws ExpiredJwtException   JWT过期异常
     * @throws MalformedJwtException JWT解析失败异常
     * @throws SignatureException    JWT格式错误异常
     * @since 1.1.0.211021
     */
    @NonNull
    public static JwtPayload parseJwtToken(@NonNull String token, @NonNull String secret)
            throws ExpiredJwtException, MalformedJwtException, SignatureException {
        Claims claims = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
        JwtPayload jwtPayload = new JwtPayload();
        jwtPayload.setJti(claims.getId());
        jwtPayload.setIss(claims.getIssuer());
        jwtPayload.setIat(claims.getIssuedAt());
        jwtPayload.setExp(claims.getExpiration());
        jwtPayload.setNbf(claims.getNotBefore());
        jwtPayload.setAud(claims.getAudience());
        jwtPayload.setSub(claims.getSubject());
        jwtPayload.setUserId(claims.get(JwtPayload.USER_ID, Long.class));
        jwtPayload.setInternal(claims.get(JwtPayload.INTERNAL, Boolean.class));
        return jwtPayload;
    }
}
import com.alibaba.ttl.TransmittableThreadLocal;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import pro.haichuang.framework.base.enums.error.client.AuthorityErrorEnum;
import pro.haichuang.framework.base.exception.client.AuthorityException;

/**
 * Security工具类
 *
 */
public class SecurityUtils {

    private static final ThreadLocal<JwtPayload> CONTEXT_HOLDER = new TransmittableThreadLocal<>();

    /**
     * 设置Context
     *
     * @param jwtPayload JWT载荷
     * @since 1.1.0.211021
     */
    public static void setJwtPayload(@NonNull JwtPayload jwtPayload) {
        Assert.notNull(jwtPayload, "Only non-null JwtPayload instances are permitted");
        CONTEXT_HOLDER.set(jwtPayload);
    }

    /**
     * 获取JWT载荷
     *
     * @return JWT载荷
     * @since 1.1.0.211021
     */
    @Nullable
    public static JwtPayload getJwtPayload() {
        return CONTEXT_HOLDER.get();
    }

    /**
     * 获取JWT载荷, 为空时则自动创建新的对象
     *
     * @return JWT载荷
     * @since 1.1.0.211021
     */
    @NonNull
    public static JwtPayload getJwtPayloadOrNewInstance() {
        return CONTEXT_HOLDER.get() == null ? new JwtPayload() : CONTEXT_HOLDER.get();
    }

    /**
     * 获取JWT载荷
     *
     * @return JWT载荷
     * @since 1.1.0.211021
     */
    @NonNull
    public static JwtPayload getJwtPayloadAndValidate() {
        JwtPayload jwtPayload = CONTEXT_HOLDER.get();
        if (jwtPayload == null) {
            throw new AuthorityException(AuthorityErrorEnum.ACCESS_BLOCKED, "获取用户信息失败");
        }
        return jwtPayload;
    }

    /**
     * 移除当前线程存储的JWT载荷
     *
     * <p>因为 {@link ThreadLocal} 底层使用的内部类 {@code ThreadLocalMap} 实现的, 生命周期为当前线程,
     * 所以不执行此方法当线程终止后 {@code ThreadLocalMap} 中的值会被JVM垃圾回收,
     * 但推荐在不需要使用的时候显性的执行此方法, 便于理解
     *
     * @since 1.1.0.211021
     */
    public static void remove() {
        CONTEXT_HOLDER.remove();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

没事搞点事做serendipity

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值