<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() + ")");
}