<aside> 💡 主要在登陆后的针对接口的鉴权

</aside>

package com.ewell.common.util;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Base64;
import java.util.Date;
import java.util.Map;

/**
 *
 * <ol>
 * <li>iss: jwt签发者</li>
 * <li>sub: jwt所面向的用户</li>
 * <li>aud: 接收jwt的一方</li>
 * <li>exp: jwt的过期时间,这个过期时间必须要大于签发时间</li>
 * <li>nbf: 定义在什么时间之前,该jwt都是不可用的</li>
 * <li>iat: jwt的签发时间</li>
 * <li>jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击</li>
 * </ol>
 *
 * @Description: JWT校验工具类
 * @Author: zhaoshijie
 * @Date: 2019-06-12
 *
 */
public class JwtUtil {
    private static Logger logger = LoggerFactory.getLogger(JwtUtil.class);
    //过期时间
    private static Long timeLimit = 60 * 30 * 1000L;

    /**
      *
      * @Description: 创建token
      * @Author: zhaoshijie
      * @Date: 2019-06-12
      *
    */
    public static String createToken(String subject, Map<String, Object> map, String secretKey){
        try {
            byte[] bytes = Base64.getEncoder().encode(secretKey.getBytes("utf-8"));
            return createToken(subject, map, bytes);
        } catch (Exception e) {
            logger.error("createToken error",e);
        }
        return null;
    }

    /**
     *
     * @Description: 创建token
     * @Author: zhaoshijie
     * @Date: 2019-06-12
     *
     */
    private static String createToken(String subject, Map<String, Object> map, byte[] secretKey) {
        String userToken = null;
        Long nowTime=System.currentTimeMillis();
        JwtBuilder builder = Jwts.builder().setSubject(subject)
                .setExpiration(new Date(nowTime + timeLimit)).setNotBefore(new Date(nowTime));
        if (map != null) {
            for (String key : map.keySet()) {
                builder.claim(key, map.get(key));
            }
        }
        userToken = builder.signWith(SignatureAlgorithm.HS512, secretKey).compact();

        return userToken;
    }

    /**
     * 解密 jwt
     *
     * @param jwt
     * @return
     * @throws Exception
     */
    public static Claims parseJWT(String jwt, String secretKey) throws Exception {
        byte[] bytes = Base64.getEncoder().encode(secretKey.getBytes("utf-8"));
        Claims claims = Jwts.parser().setSigningKey(bytes).parseClaimsJws(jwt).getBody();
        return claims;
    }
}
if (StringUtils.isNotBlank(accessToken)) {
            try {
                claims = JwtUtil.parseJWT(accessToken, ConstantsUtil.SECRET_KEY);

                if (claims == null) {
                    this.stopZuulRoutingWithError(ctx, HttpStatus.UNAUTHORIZED,
                            "Error AccessToken for the API (" + request.getRequestURI().toString() + ")");
                    return null;
                }
                logger.info("claims is:{}", claims);
                if (claims.getSubject().equals(ConstantsUtil.ZKKY_USEE)){
                    if(claims.get(ConstantsUtil.USERID)!=null) {
                        Long userId = Long.parseLong(claims.get(ConstantsUtil.USERID).toString());
                        //用户是否存在校验
                        UserInfo userInfo = userAuthRedis.getUserInfo(userId);

                        logger.info("userId:{}", userId);
                        Map<String, Object> map = Maps.newHashMapWithExpectedSize(1);
                        map.put(ConstantsUtil.USERID,userId.toString());
                        map.put(ConstantsUtil.LASTLOGINTIME,userInfo.getLastLoginTime());

                        String token = JwtUtil.createToken(ConstantsUtil.ZKKY_USEE, map, ConstantsUtil.SECRET_KEY);
                        response.setHeader(ConstantsUtil.TOKEN, token);

                        Long lastLoginTime = Long.parseLong(claims.get(ConstantsUtil.LASTLOGINTIME).toString());

                        if (!(userInfo.getLastLoginTime().getTime() == lastLoginTime)) {
                            this.stopZuulRoutingWithError(ctx, HttpStatus.UNAUTHORIZED,
                                    "Exceed the time limit AccessToken for the API (" + request.getRequestURI().toString() + ")");
                        }
                        if (userInfo != null && userInfo.thisSingleLogin()) {
                            //单点登入在壳那边被注销
                            EwellPortalMessage ewellPortalMessage = singleLoginClient.tokenByPortal(userInfo.getAppId(), userInfo.getToken());
                            if (!ewellPortalMessage.thisSucceedFlag()) {
                                this.stopZuulRoutingWithError(ctx, HttpStatus.UNAUTHORIZED, "登录信息已过期!");
                            }
                        } else {
                            //缓存没有的情况,1.从未登入(浏览器无缓存),2.修改权限导致强行登出(浏览器有缓存)
                            if (userInfo == null) {
                                this.stopZuulRoutingWithError(ctx, HttpStatus.UNAUTHORIZED, "用户未登陆");
                            }
                        }
                        // 3. set userInfo to HTTP header
                        ctx.addZuulRequestHeader(ConstantsUtil.USER_ID, userId.toString());

                        logger.info("ZuulRequestHeaders userInfo: {}", ctx.getZuulRequestHeaders().get(ConstantsUtil.USER_ID));
                        
                    }

                }

            } catch (Exception e) {
                this.stopZuulRoutingWithError(ctx, HttpStatus.UNAUTHORIZED,
                        "Error AccessToken for the API (" + request.getRequestURI().toString() + ")");
                return null;
            }
        } else {
            this.stopZuulRoutingWithError(ctx, HttpStatus.UNAUTHORIZED,
                    "AccessToken is needed for the API (" + request.getRequestURI().toString() + ")");
        }