Jwt简介
1、Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。 2、JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。 3、JWT生成的token是无状态的,服务端不存储,即一旦生成在有效期之前一直可用,无法销毁。 4、如果需要刷新token有效期或者提前失效需要借助缓存、数据库或者redis来自己实现对应逻辑
操作流程
1、新建JwtUtil类
public class JwtUtil {
private static final int EXPIRE_TIME = 30;
private static final String TOKEN_SECRET = "privateKey";
private static final String USER_NAME = "name";
public static String createToken(Long userId, String userName) {
Calendar nowTime = Calendar.getInstance();
nowTime.add(Calendar.MINUTE,EXPIRE_TIME);
Date expiresDate = nowTime.getTime();
String token= JWT.create().withAudience(userId+"")
.withIssuedAt(new Date())
.withExpiresAt(expiresDate)
.withClaim(USER_NAME, userName)
.sign(Algorithm.HMAC256(userId+TOKEN_SECRET));
return token;
}
public static boolean verifyToken(String token, String secret) {
try {
JWTVerifier verifier = JWT.require(Algorithm.HMAC256(secret+TOKEN_SECRET)).build();
verifier.verify(token);
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
public static String getAudience(String token) throws Exception {
String audience = null;
try {
audience = JWT.decode(token).getAudience().get(0);
} catch (JWTDecodeException j) {
}
return audience;
}
2、新建WebMvcConfig文件
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/login/**","/error"
,"/swagger-ui.html/**","/swagger-resources/**");
}
@Bean
public LoginInterceptor loginInterceptor(){
return new LoginInterceptor();
}
}
3、新建NoNeedToken注解
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface NoNeedToken {
}
4、新建LoginInterceptor文件
public class LoginInterceptor implements HandlerInterceptor {
protected Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private SysUserService sysUserService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String token = request.getHeader("token");
logger.info("已进入拦截器,当前访问地址为:" + request.getRequestURI());
if (!(handler instanceof HandlerMethod)) {
return true;
}
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
if (method.isAnnotationPresent(NoNeedToken.class)) {
return true;
} else {
if (token == null) {
logger.warn("登录失效");
return false;
}
String userId = JwtUtil.getAudience(token);
SysUser user = sysUserService.getById(Long.valueOf(userId));
if (user == null) {
logger.warn("该用户不存在!");
return false;
}
boolean r = JwtUtil.verifyToken(token, userId);
if (r){
logger.info("验证成功");
}else{
logger.info("验证失败");
return false;
}
return true;
}
}
}
5、在controller层上不需要验证token的方法上添加@NoNeedToken
|