java中token生成,验证等功能实现

直接上代码

1、首先配置一下token相关的参数

jwt:
  user-secret-key: xxxxxx 
  user-ttl: 72 # 令牌有效期(小时)

这两个随便填都可以的

2、我是直接创建了一个工具类用于有关token的操作

import com.ahalif.gongzhonghao.properties.JwtProperties;
import io.jsonwebtoken.*;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.http.HttpHeaders;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.Date;

/**
 * JWT令牌工具类,用于生成、验证和刷新用户令牌
 */
@Component
public class UserTokenUtils {

    private final JwtProperties jwtProperties;
    private static final Logger logger = LoggerFactory.getLogger(UserTokenUtils.class);

    // JWT签名算法
    private static final SignatureAlgorithm SIGNATURE_ALGORITHM = SignatureAlgorithm.HS256;

    @Autowired
    public UserTokenUtils(JwtProperties jwtProperties) {
        this.jwtProperties = jwtProperties;

        // 检查密钥是否为空
        if (jwtProperties.getUserSecretKey() == null || jwtProperties.getUserSecretKey().isEmpty()) {
            logger.error("JWT密钥未配置!请检查application.properties中的jwt.user-secret-key配置");
            throw new IllegalArgumentException("JWT密钥不能为空");
        }
    }

    /**
     * 生成JWT令牌
     * @param personId 用户ID
     * @return JWT令牌
     */
    public String generateToken(String personId) {
        long expirationTime = jwtProperties.getUserTtl() * 60 * 60 * 1000; // 转换为毫秒,默认72小时
        
        return Jwts.builder()
                .setSubject(personId)
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + expirationTime))
                .signWith(SIGNATURE_ALGORITHM, jwtProperties.getUserSecretKey())
                .compact();
    }

    /**
     * 验证JWT令牌
     * @param token JWT令牌
     * @return 解析后的JWT声明
     * @throws JwtException 令牌验证失败时抛出异常
     */
    public Claims validateToken(String token) throws JwtException {
        return Jwts.parser()
                .setSigningKey(jwtProperties.getUserSecretKey())
                .parseClaimsJws(token)
                .getBody();
    }

    /**
     * 刷新JWT令牌(延长有效期)
     * @param token 原始JWT令牌
     * @return 刷新后的JWT令牌
     * @throws JwtException 令牌验证失败时抛出异常
     */
    public String refreshToken(String token) throws JwtException {
        Claims claims = validateToken(token);
        return generateToken(claims.getSubject());
    }

    /**
     * 从令牌中获取用户ID
     * @param token JWT令牌
     * @return 用户ID
     * @throws JwtException 令牌验证失败时抛出异常
     */
    public String getPersonIdFromToken(String token) throws JwtException {
        return validateToken(token).getSubject();
    }

    /**
     * 从HTTP请求中提取JWT令牌
     * @return 提取的JWT令牌,若请求中未包含令牌则返回null
     */
    public String getTokenFromRequest() {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes != null) {
            HttpServletRequest request = attributes.getRequest();
            String authHeader = request.getHeader(HttpHeaders.AUTHORIZATION);
            if (authHeader != null && authHeader.startsWith("Bearer ")) {
                return authHeader.substring(7); // 提取"Bearer "后的令牌
            }
        }
        return null; // 若未找到令牌,则返回null
    }
}

3、相关的类

import com.alibaba.fastjson2.JSONObject;
import io.jsonwebtoken.JwtException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import java.io.IOException;
import java.io.PrintWriter;

/**
 * JWT令牌拦截器,用于验证请求中的令牌
 */
@Component
public class JwtInterceptor implements HandlerInterceptor {

    private static final Logger logger = LoggerFactory.getLogger(JwtInterceptor.class);

    @Autowired
    private UserTokenUtils userTokenUtils;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 排除登录路径
        if (request.getRequestURI().contains("/denglu")
                ||request.getRequestURI().contains("/add")
        ) {
            return true;
        }

        // 从请求头中获取令牌
        String token = request.getHeader("Authorization");

        // 验证令牌
        try {
            if (token != null && token.startsWith("Bearer ")) {
                token = token.substring(7); // 去掉"Bearer "前缀

                // 验证令牌有效性
                userTokenUtils.validateToken(token);

                // 刷新令牌(延长有效期)
                String refreshedToken = userTokenUtils.refreshToken(token);
                response.setHeader("Authorization", "Bearer " + refreshedToken);

                logger.info("令牌验证成功,路径: {}", request.getRequestURI());
                return true;
            } else {
                // 没有提供令牌
                logger.warn("缺少令牌,路径: {}", request.getRequestURI());
                sendErrorResponse(response, "缺少令牌");
                return false;
            }
        } catch (JwtException e) {
            // 令牌验证失败
            logger.error("无效的令牌,路径: {}", request.getRequestURI(), e);
            sendErrorResponse(response, "无效的令牌");
            return false;
        }
    }

    private void sendErrorResponse(HttpServletResponse response, String message) throws IOException {
        response.setContentType("application/json;charset=UTF-8");
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);

        Result<String> result = Result.error(message);
        String jsonResult = JSONObject.toJSONString(result);

        try (PrintWriter writer = response.getWriter()) {
            writer.write(jsonResult);
            writer.flush();
        }
    }
}

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

@Configuration
@ConfigurationProperties(prefix = "jwt")
public class JwtProperties {

    private String userSecretKey;
    private long userTtl = 72; // 默认72小时

    public String getUserSecretKey() {
        return userSecretKey;
    }

    public void setUserSecretKey(String userSecretKey) {
        this.userSecretKey = userSecretKey;
    }

    public long getUserTtl() {
        return userTtl;
    }

    public void setUserTtl(long userTtl) {
        this.userTtl = userTtl;
    }
}

最最最重要的,写完后启动类上要加注解

大概就是这样了,如有错误,请各位大佬指正

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值