JWT 令牌
引入依赖
xml
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>配置类
java
/**
* jw配置文件
*/
@Setter
@Getter
@NoArgsConstructor
@ToString
@Configuration
@ConfigurationProperties(prefix = "") // 填写项目中的 prefix
public class JwtTokenManagerProperties implements Serializable {
/**
* 签名密码
*/
private String base64EncodedSecretKey;
/**
* 有效时间
*/
private Integer ttl;
}JWTUtils
java
public class JwtUtils {
/**
* 生成jwt
* 使用Hs256算法, 私匙使用固定秘钥
*
* @param secretKey jwt秘钥
* @param dateOffset jwt过期时间(小时)
* @param claims 设置的信息
* @return
*/
public static String createJWT(String secretKey , int dateOffset, Map<String, Object> claims) {
// 指定签名的时候使用的签名算法,也就是header那部分
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
// 设置jwt的body
JwtBuilder builder = Jwts.builder()
// 如果有私有声明,一定要先设置这个自己创建的私有的声明,这个是给builder的claim赋值,一旦写在标准的声明赋值之后,就是覆盖了那些标准的声明的
.setClaims(claims)
// 设置签名使用的签名算法和签名使用的秘钥
.signWith(signatureAlgorithm, secretKey.getBytes(StandardCharsets.UTF_8))
// 设置过期时间
.setExpiration(DateUtil.offset(new Date(), DateField.HOUR_OF_DAY, dateOffset));
return builder.compact();
}
/**
* Token解密
*
* @param secretKey jwt秘钥 此秘钥一定要保留好在服务端, 不能暴露出去, 否则sign就可以被伪造, 如果对接多个客户端建议改造成多个
* @param token 加密后的token
* @return
*/
public static Claims parseJWT(String secretKey, String token) {
try {
// 得到DefaultJwtParser
Claims claims = Jwts.parser()
// 设置签名的秘钥
.setSigningKey(secretKey.getBytes(StandardCharsets.UTF_8))
// 设置需要解析的jwt
.parseClaimsJws(token).getBody();
return claims;
} catch (Exception e) {
// throw new AccessDeniedException("没有权限,请登录");
throw new RuntimeException("没有权限,请登录");
}
}
}拦截器解析
java
@Component
public class UserInterceptor implements HandlerInterceptor {
@Autowired
private JwtTokenManagerProperties jwtTokenManagerProperties;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//判断当前请求是否是handler()
if(!(handler instanceof HandlerMethod)){
return true;
}
//获取token
String token = request.getHeader(Constants.USER_TOKEN);
if(StringUtils.isEmpty(token)){
throw new BaseException(BasicEnum.SECURITY_ACCESSDENIED_FAIL);
}
//解析token
Map<String, Object> claims = JwtUtil.parseJWT(jwtTokenManagerProperties.getBase64EncodedSecretKey(), token);
if(ObjectUtil.isEmpty(claims)){
throw new BaseException(BasicEnum.SECURITY_ACCESSDENIED_FAIL);
}
//Long userId = (Long) claims.get(Constants.JWT_USERID);
Long userId = MapUtil.get(claims, Constants.JWT_USERID, Long.class);
if(ObjectUtil.isEmpty(userId)){
throw new BaseException(BasicEnum.SECURITY_ACCESSDENIED_FAIL);
}
//把数据存储到线程中
UserThreadLocal.set(userId);
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
UserThreadLocal.remove();
}
}