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 {
//过期时间 30min
private static final int EXPIRE_TIME = 30;
//私钥
private static final String TOKEN_SECRET = "privateKey";
private static final String USER_NAME = "name";
/**
* 签发对象:这个用户的id
* 签发时间:现在
* 有效时间:30分钟
* 载荷内容:暂时设计为:这个人的名字
* 加密密钥:这个人的id加上一串字符串
*/
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;
}
/**
* 检验合法性,其中secret参数就应该传入的是用户的id
*/
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) {
//这里是token解析失败
}
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();
//检查是否有NoNeedToken注释,有则跳过认证
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