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