SpringBoot2-Jwt

1.官网

jwt.io/libraries

2.选jose4j

    pom


   org.bitbucket.b_c
   jose4j
   0.9.4

3.创建jwt工具

public class JwtUtil {

    private static  String secret = "e0e775bfcad04ecc94807b028dfca4d5";// "12345678123456781234567812345678"; // 注意密钥长短(最少32个字符)
    private static String Issuer = "QiXiao";
    private static String Audience = "WangPeng";

    public static String CreateToken(UserEntity user)  {

        try {
            JsonWebSignature jws = new JsonWebSignature();

            //Claim
            JwtClaims claims = new JwtClaims();
            claims.setIssuer(Issuer);  // who creates the token and signs it
            claims.setAudience(Audience); // to whom the token is intended to be sent
            claims.setExpirationTimeMinutesInTheFuture(10); // 过期时间
            claims.setGeneratedJwtId();                     // 为 JWT 设置一个自动生成的唯一 ID
            claims.setIssuedAtToNow();                      // 设置 Token 发布/创建 时间为当前时间
            claims.setNotBeforeMinutesInThePast(2);         // 设置生效时间为 2 分钟前
            claims.setSubject("Bearer"); // the subject/principal is whom the token is about
            claims.setClaim("UserSN", user.getSN());
            claims.setClaim("email","[email protected]"); // additional claims/attributes about the subject can be added

            jws.setPayload(claims.toJson());

            //Header
            jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.HMAC_SHA256);
            jws.setHeader("typ", "JWT");

            //签名
            Key hmacKey = CreateKey();
            jws.setKey(hmacKey);
            jws.setDoKeyValidation(false);

            String jwt = jws.getCompactSerialization();
            System.out.println(jwt);
            return jwt;
        }
        catch (JoseException ex)
        {
            throw new RuntimeException(ex.getMessage());
        }

    }

    private static Key CreateKey()
    {
        Key hmacKey = new HmacKey(secret.getBytes());
        return hmacKey;
    }

    public static JwtClaims ValidateToken(String jwt) throws MalformedClaimException {

        String message = "";
        Key key = CreateKey();
        JwtClaims jwtClaims = new JwtClaims();

        // 验证令牌
        JwtConsumer jwtConsumer = new JwtConsumerBuilder()
                .setAllowedClockSkewInSeconds(30)
                .setRequireExpirationTime()     // 必须设置过期时间
                .setRequireSubject()            // 必须设置 Subject
                .setExpectedIssuer(Issuer)    // 必须设置 Token 签发者
                .setExpectedAudience(Audience)// 必须设置 Token 签发给谁
                .setVerificationKey(key)    // 设置用于验证签名的公钥
                // 设置允许的预期签名算法
                .setJwsAlgorithmConstraints(
                        AlgorithmConstraints.ConstraintType.WHITELIST, AlgorithmIdentifiers.HMAC_SHA256)
                .build();

        try {
            jwtClaims = jwtConsumer.processToClaims(jwt);
        }
        catch(InvalidJwtException e)
        {
            jwtClaims = new JwtClaims();
            message = handleException(e);
            jwtClaims.setClaim("error", message);
        }

        return jwtClaims;
    }

    private static String handleException(InvalidJwtException e){
        String message = "";

        try {
            JwtClaims jwtClaims = e.getJwtContext().getJwtClaims();

            List errorDetails = e.getErrorDetails();

            // 异常是否因 JWT 过期触发
            if (e.hasExpired())
            {
                message = "token已经过期, 过期时间在" + jwtClaims.getExpirationTime();
            }

            // 异常是否因 Audience 无效触发
            if(e.hasErrorCode(ErrorCodes.AUDIENCE_INVALID))
            {
                message = "无效audience:" + jwtClaims.getAudience();
            }

            // 异常是否因缺少 Audience 触发
            if (e.hasErrorCode(ErrorCodes.AUDIENCE_MISSING)) {
                message = "Audience丢失";
            }

            // 异常是否因缺少过期时间触发
            if (e.hasErrorCode(ErrorCodes.EXPIRATION_MISSING)) {
                message = "缺少过期时间";
            }


            // 异常是否因过期时间太长触发
            if (e.hasErrorCode(ErrorCodes.EXPIRATION_TOO_FAR_IN_FUTURE)) {
                message = "过期时间太";
            }
            // 异常是否因缺乏完整性触发
            if (e.hasErrorCode(ErrorCodes.INTEGRITY_MISSING)) {
                message = "缺乏完整性";
            }
            // 异常是否因发布时间无效触发
            if (e.hasErrorCode(ErrorCodes.ISSUED_AT_INVALID_FUTURE) || e.hasErrorCode(ErrorCodes.ISSUED_AT_INVALID_PAST)) {
                message = "发布时间无效:" + jwtClaims.getIssuedAt();
            }

            // 异常是否因缺少发布时间触发
            if (e.hasErrorCode(ErrorCodes.ISSUED_AT_MISSING)) {
                message = "缺少发布时间:";
            }
            // 异常是否因签发者无效触发
            if (e.hasErrorCode(ErrorCodes.ISSUER_INVALID)) {
                message = "签发者无效:" + jwtClaims.getIssuer();
            }
            // 异常是否因缺少签发者触发
            if (e.hasErrorCode(ErrorCodes.ISSUER_MISSING)) {
                message = "缺少签发者";
            }
            // 异常是否因 JSON 无效触发
            if (e.hasErrorCode(ErrorCodes.JSON_INVALID)) {
                message = "JSON 无效";
            }
            // 异常是否因缺少 JWT ID 触发
            if (e.hasErrorCode(ErrorCodes.JWT_ID_MISSING)) {
                message = "缺少 JWT ID";
            }
            // 异常是否因 JwtClaims 格式错误触发
            if (e.hasErrorCode(ErrorCodes.MALFORMED_CLAIM)) {
                message = "JwtClaims 格式错误";
            }
            // 异常是否因缺少生效时间触发
            if (e.hasErrorCode(ErrorCodes.NOT_BEFORE_MISSING)) {
                message = "缺少生效时间";
            }
            // 异常是否因 Token 尚未生效触发
            if (e.hasErrorCode(ErrorCodes.NOT_YET_VALID)) {
                message = "Token 尚未生效";
            }
            // 异常是否因 Token 的 Signature 部分无效触发
            if (e.hasErrorCode(ErrorCodes.SIGNATURE_INVALID)) {
                message = "Token 的 Signature 部分无效";
            }
            // 异常是否因 Token 的 Signature 部分缺失触发
            if (e.hasErrorCode(ErrorCodes.SIGNATURE_MISSING)) {
                message = "Token 的 Signature 部分缺失";
            }
            // 异常是否因 Subject 无效触发
            if (e.hasErrorCode(ErrorCodes.SUBJECT_INVALID)) {
                message = "Subject 无效";
            }
            // 异常是否因 Subject 缺失触发
            if (e.hasErrorCode(ErrorCodes.SUBJECT_MISSING)) {
                message = "Subject 缺失";
            }
            // 异常是否因 Type 无效触发
            if (e.hasErrorCode(ErrorCodes.TYPE_INVALID)) {
                message = "Type 无效";
            }
            // 异常是否因 Type 缺失触发
            if (e.hasErrorCode(ErrorCodes.TYPE_MISSING)) {
                message = "Type 缺失";
            }

            if(message == "")
            {
                message = e.getMessage();
            }
        }
        catch (MalformedClaimException e1) {
            message = e.getMessage();
        }

        return message;
    }
}

4.CreateToken方法在登录时用

5.验证token的方法ValidateToken在拦截器用

public class JwtHandlerInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        boolean bOK = HandlerInterceptor.super.preHandle(request, response, handler);

        String header = request.getHeader("Authorization");

        // 请求头不为空进行解析
        if (StringUtils.isNotBlank(header) && header.startsWith("Bearer ")) {

            // 得到令牌
            String jwt = header.substring(7);
            JwtClaims jwtClaims = JwtUtil.ValidateToken(jwt);

            Object msg = jwtClaims.getClaimValue("error");
            if(msg != null)
            {
                response.setContentType("text/html;charset=UTF-8");
                response.getWriter().write((String) msg);
            }
            else
            {
                Map map = new HashMap<>();
                map.put("UserSN", jwtClaims.getClaimValue("UserSN"));
                request.setAttribute("UserInfo", map);
            }

            return msg == null;

        }
        return false;
    }


    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}

6.获取UserSN

Controller里要用到token的UserSN,通过RequestContextHolder可以获取,创建WebUtil


import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;
 
public class WebUtil {

    private static HttpServletRequest request;

    static
    {
        if(request == null)
        {
            request =  ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
        }
    }

    public static long getUserSN()
    {
        Object attribute = request.getAttribute("UserInfo");
        if(attribute != null && attribute instanceof Map)
        {
            Map map =   (Map)attribute;

            return (long) map.get("UserSN");
        }
        return 0;
    }
}

7.

你可能感兴趣的:(SpringBoot,java,服务器,前端)