1.官网
jwt.io/libraries
2.选jose4j
pom
<dependency><groupId>org.bitbucket.b_c</groupId><artifactId>jose4j</artifactId><version>0.9.4</version>
</dependency>
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();//ClaimJwtClaims claims = new JwtClaims();claims.setIssuer(Issuer); // who creates the token and signs itclaims.setAudience(Audience); // to whom the token is intended to be sentclaims.setExpirationTimeMinutesInTheFuture(10); // 过期时间claims.setGeneratedJwtId(); // 为 JWT 设置一个自动生成的唯一 IDclaims.setIssuedAtToNow(); // 设置 Token 发布/创建 时间为当前时间claims.setNotBeforeMinutesInThePast(2); // 设置生效时间为 2 分钟前claims.setSubject("Bearer"); // the subject/principal is whom the token is aboutclaims.setClaim("UserSN", user.getSN());claims.setClaim("email","wang_peng_yl@126.com"); // additional claims/attributes about the subject can be addedjws.setPayload(claims.toJson());//Headerjws.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<ErrorCodeValidator.Error> 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 {@Overridepublic 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<String,Object> map = new HashMap<>();map.put("UserSN", jwtClaims.getClaimValue("UserSN"));request.setAttribute("UserInfo", map);}return msg == null;}return false;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);}@Overridepublic 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<String,Object> map = (Map<String,Object>)attribute;return (long) map.get("UserSN");}return 0;}
}
7.