JSON Web Tokens 工具类 [ JwtUtil ]
<dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.0</version> </dependency>
package com.app.core.util; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jws; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import io.jsonwebtoken.impl.crypto.MacProvider; import lombok.extern.log4j.Log4j2; import org.apache.commons.codec.binary.Base64; import org.apache.commons.lang3.StringUtils; import org.joda.time.DateTime; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import java.security.Key; import java.util.Date; import java.util.UUID; /** * JWT校验工具类 * <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> */ @Log4j2 public class JwtUtil { /** * JWT 加解密类型 */ private static final SignatureAlgorithm JWT_ALG = SignatureAlgorithm.HS256; /** * JWT 生成密钥使用的密码 */ private static final String JWT_RULE = "wjtree.xin"; /** * JWT 添加至HTTP HEAD中的前缀 */ private static final String JWT_SEPARATOR = "Bearer "; /** * 使用JWT默认方式,生成加解密密钥 * * @param alg 加解密类型 * @return */ public static SecretKey generateKey(SignatureAlgorithm alg) { return MacProvider.generateKey(alg); } /** * 使用指定密钥生成规则,生成JWT加解密密钥 * * @param alg 加解密类型 * @param rule 密钥生成规则 * @return */ public static SecretKey generateKey(SignatureAlgorithm alg, String rule) { // 将密钥生成键转换为字节数组 byte[] bytes = Base64.decodeBase64(rule); // 根据指定的加密方式,生成密钥 return new SecretKeySpec(bytes, alg.getJcaName()); } /** * 构建JWT * * @param alg jwt 加密算法 * @param key jwt 加密密钥 * @param sub jwt 面向的用户 * @param aud jwt 接收方 * @param jti jwt 唯一身份标识 * @param iss jwt 签发者 * @param nbf jwt 生效日期时间 * @param duration jwt 有效时间,单位:秒 * @return JWT字符串 */ public static String buildJWT(SignatureAlgorithm alg, Key key, String sub, String aud, String jti, String iss, Date nbf, Integer duration) { // jwt的签发时间 DateTime iat = DateTime.now(); // jwt的过期时间,这个过期时间必须要大于签发时间 DateTime exp = null; if (duration != null) exp = (nbf == null ? iat.plusSeconds(duration) : new DateTime(nbf).plusSeconds(duration)); // 获取JWT字符串 String compact = Jwts.builder() .signWith(alg, key) .setSubject(sub) .setAudience(aud) .setId(jti) .setIssuer(iss) .setNotBefore(nbf) .setIssuedAt(iat.toDate()) .setExpiration(exp != null ? exp.toDate() : null) .compact(); // 在JWT字符串前添加"Bearer "字符串,用于加入"Authorization"请求头 return JWT_SEPARATOR + compact; } /** * 构建JWT * * @param sub jwt 面向的用户 * @param aud jwt 接收方 * @param jti jwt 唯一身份标识 * @param iss jwt 签发者 * @param nbf jwt 生效日期时间 * @param duration jwt 有效时间,单位:秒 * @return JWT字符串 */ public static String buildJWT(String sub, String aud, String jti, String iss, Date nbf, Integer duration) { return buildJWT(JWT_ALG, generateKey(JWT_ALG, JWT_RULE), sub, aud, jti, iss, nbf, duration); } /** * 构建JWT * * @param sub jwt 面向的用户 * @param jti jwt 唯一身份标识,主要用来作为一次性token,从而回避重放攻击 * @return JWT字符串 */ public static String buildJWT(String sub, String jti, Integer duration) { return buildJWT(sub, null, jti, null, null, duration); } /** * 构建JWT * <p>使用 UUID 作为 jti 唯一身份标识</p> * <p>JWT有效时间 600 秒,即 10 分钟</p> * * @param sub jwt 面向的用户 * @return JWT字符串 */ public static String buildJWT(String sub) { return buildJWT(sub, null, UUID.randomUUID().toString(), null, null, 600); } /** * 解析JWT * * @param key jwt 加密密钥 * @param claimsJws jwt 内容文本 * @return {@link Jws} * @throws Exception */ public static Jws<Claims> parseJWT(Key key, String claimsJws) { // 移除 JWT 前的"Bearer "字符串 claimsJws = StringUtils.substringAfter(claimsJws, JWT_SEPARATOR); // 解析 JWT 字符串 return Jwts.parser().setSigningKey(key).parseClaimsJws(claimsJws); } /** * 校验JWT * * @param claimsJws jwt 内容文本 * @return ture or false */ public static Boolean checkJWT(String claimsJws) { boolean flag = false; try { SecretKey key = generateKey(JWT_ALG, JWT_RULE); // 获取 JWT 的 payload 部分 flag = (parseJWT(key, claimsJws).getBody() != null); } catch (Exception e) { log.warn("JWT验证出错,错误原因:{}", e.getMessage()); } return flag; } /** * 校验JWT * * @param key jwt 加密密钥 * @param claimsJws jwt 内容文本 * @param sub jwt 面向的用户 * @return ture or false */ public static Boolean checkJWT(Key key, String claimsJws, String sub) { boolean flag = false; try { // 获取 JWT 的 payload 部分 Claims claims = parseJWT(key, claimsJws).getBody(); // 比对JWT中的 sub 字段 flag = claims.getSubject().equals(sub); } catch (Exception e) { log.warn("JWT验证出错,错误原因:{}", e.getMessage()); } return flag; } /** * 校验JWT * * @param claimsJws jwt 内容文本 * @param sub jwt 面向的用户 * @return ture or false */ public static Boolean checkJWT(String claimsJws, String sub) { return checkJWT(generateKey(JWT_ALG, JWT_RULE), claimsJws, sub); } }
package com.app.web.core; import com.app.core.util.JwtUtil; import lombok.extern.log4j.Log4j2; import org.apache.commons.lang3.StringUtils; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * 请求鉴权拦截器 */ @Log4j2 public class AuthorizationInterceptor extends HandlerInterceptorAdapter { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { boolean flag = false; // 获取 HTTP HEAD 中的 TOKEN String authorization = request.getHeader("Authorization"); // 校验 TOKEN flag = StringUtils.isNotBlank(authorization) ? JwtUtil.checkJWT(authorization) : false; // 如果校验未通过,返回 401 状态 if (!flag) response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); return flag; } }
相关推荐
-
多线程同时下载网页中的所有图片,完成后返回 java
2019-1-13
-
java从图片中识别文字 java
2019-1-8
-
JSON工具类 java
2019-1-12
-
数字金额转中文大写 java
2019-1-7
-
Java版跳一跳 java
2019-1-13
-
java执行bat代码 java
2019-1-8
-
Java工具类-基于SnowFlake的短地址生成器 java
2019-1-7
-
java缓冲队列 java
2019-1-8
-
java微信接口 java
2019-1-8
-
quartz 通用的多线程定时任务 java
2019-1-7