package com.gkhy.assess.common.utils;
|
|
import cn.hutool.core.date.DateUtil;
|
import cn.hutool.crypto.digest.DigestUtil;
|
import com.auth0.jwt.JWT;
|
import com.auth0.jwt.JWTVerifier;
|
import com.auth0.jwt.algorithms.Algorithm;
|
import com.auth0.jwt.exceptions.JWTDecodeException;
|
import com.auth0.jwt.interfaces.Claim;
|
import com.auth0.jwt.interfaces.DecodedJWT;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.gkhy.assess.common.api.CommonResult;
|
import com.gkhy.assess.common.exception.ApiException;
|
import io.swagger.models.auth.In;
|
import org.apache.commons.lang3.StringUtils;
|
import org.apache.shiro.crypto.hash.Md5Hash;
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
|
import javax.servlet.ServletResponse;
|
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletResponse;
|
import java.io.IOException;
|
import java.io.OutputStream;
|
import java.util.Date;
|
import java.util.HashMap;
|
import java.util.Map;
|
|
/**
|
* JwtToken生成的工具类
|
* JWT token的格式:header.payload.signature
|
* header的格式(算法、token的类型):
|
* {"alg": "HS512","typ": "JWT"}
|
* payload的格式(用户名、创建时间、生成时间):
|
* {"sub":"wang","created":1489079981393,"exp":1489684781}
|
* signature的生成算法:
|
* HMACSHA512(base64UrlEncode(header) + "." +base64UrlEncode(payload),secret)
|
*/
|
public class JwtTokenUtil {
|
private static final Logger LOGGER = LoggerFactory.getLogger(JwtTokenUtil.class);
|
|
public static final String USER_LOGIN_TOKEN="Authorization";
|
|
public static final String CLAIM_KEY_USERNAME = "sub";
|
public static final String CLAIM_KEY_CREATED = "created";
|
|
public static String SECRET="nms-secret";
|
|
public static String tokenHead="";
|
|
/**Token有效期为1天(Token在reids中缓存时间为两倍) 单位ms*/
|
public static final long EXPIRATION=(1 *12) * 60 * 60 * 1000; //JWT的超期限时间(60*60*24*1)
|
|
/**
|
* token有效期还有30分钟,刷新token 单位ms
|
*/
|
public static final long NEED_UPDATE_TIME= 30 * 60 * 1000;
|
|
/**
|
* 校验token是否正确
|
* @param token
|
* @param username
|
* @param secret 用户密码
|
* @return
|
*/
|
public static boolean verify(String token,String username,String secret,Integer identity){
|
try {
|
Algorithm algorithm = Algorithm.HMAC256(secret);
|
JWTVerifier verifier = JWT.require(algorithm).withClaim("username", username)
|
.withClaim("identity",identity).build();
|
DecodedJWT jwt = verifier.verify(token);
|
return true;
|
}catch (Exception e){
|
return false;
|
}
|
}
|
|
|
public static boolean isNeedUpdate(String token, String username, String secret,Integer identity){
|
Date expertsAt =null;
|
try {
|
Algorithm algorithm = Algorithm.HMAC256(secret);
|
JWTVerifier verifier = JWT.require(algorithm).withClaim("username", username)
|
.withClaim("identity",identity).build();
|
expertsAt = verifier.verify(token).getExpiresAt();
|
}catch (Exception e){
|
throw new ApiException("token非法无效");
|
}
|
//如果剩余过期时间少于过期时常的一半时 需要更新
|
return (expertsAt.getTime()-System.currentTimeMillis()) < NEED_UPDATE_TIME;
|
}
|
|
/**
|
* 获取token中的信息 无需secret解密也能获得
|
* @param token
|
* @return
|
*/
|
public static String getUsername(String token){
|
try {
|
DecodedJWT jwt = JWT.decode(token);
|
return jwt.getClaim("username").asString();
|
}catch (JWTDecodeException e){
|
return null;
|
}
|
}
|
|
/**
|
* 获取token中的信息 无需secret解密也能获得
|
* @param token
|
* @return
|
*/
|
public static Integer getIdentity(String token){
|
try {
|
DecodedJWT jwt = JWT.decode(token);
|
return jwt.getClaim("identity").asInt();
|
}catch (JWTDecodeException e){
|
return null;
|
}
|
}
|
|
|
|
/**
|
* 生成签名
|
* @param username
|
* @param secret
|
* @return
|
*/
|
public static String sign(String username,String secret,Integer identity){
|
Date date=new Date(System.currentTimeMillis()+EXPIRATION);
|
Algorithm algorithm=Algorithm.HMAC256(secret);
|
return JWT.create().withClaim("username",username)
|
.withClaim("identity",identity).withExpiresAt(date).sign(algorithm);
|
}
|
|
/**
|
* 根据request中的token获取用户账号
|
*
|
* @param request
|
* @return
|
* @throws ApiException
|
*/
|
public static String getUserNameByToken(HttpServletRequest request) throws ApiException {
|
String accessToken = request.getHeader(USER_LOGIN_TOKEN);
|
String username = getUsername(accessToken);
|
if (StringUtils.isEmpty(username)) {
|
throw new ApiException("未获取到用户");
|
}
|
return username;
|
}
|
|
|
/**
|
* md5加密
|
* @param token
|
* @return
|
*/
|
public static String md5Encode(String token){
|
|
return DigestUtil.md5Hex(token);
|
}
|
|
|
/**
|
* 密码加密
|
* @param username
|
* @param password
|
* @param salt
|
* @return
|
*/
|
public static String encryptPassword(String username,String password,String salt){
|
if(salt==null){
|
salt="";
|
}
|
return new Md5Hash(username+password+salt).toHex();
|
}
|
|
|
/**
|
*
|
* @param response
|
* @param code
|
* @param errorMsg
|
*/
|
public static void responseError(ServletResponse response, String errorMsg) {
|
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
|
// issues/I4YH95浏览器显示乱码问题
|
httpServletResponse.setHeader("Content-type", "text/html;charset=UTF-8");
|
CommonResult jsonResult = CommonResult.failed(errorMsg);
|
OutputStream os = null;
|
try {
|
os = httpServletResponse.getOutputStream();
|
httpServletResponse.setCharacterEncoding("UTF-8");
|
// httpServletResponse.setStatus(code);
|
os.write(new ObjectMapper().writeValueAsString(jsonResult).getBytes("UTF-8"));
|
os.flush();
|
os.close();
|
} catch (IOException e) {
|
e.printStackTrace();
|
}
|
}
|
|
|
|
}
|