想起前段时间写的写的拦截器,自定义注解进行登录验证
拦截请求,校验有误自定义的注解,有注解就需要校验token,无注解即放行
这样的好处就是在comment中写一个,整个项目都可以用,哪里需要检验就加在那个方法上,很是灵活方便
废话不少,上代码
自定义的注解类
/**
* 在需要登录验证的Controller的方法上使用此注解
*/
@Target({ElementType.METHOD})// 可用在方法名上
@Retention(RetentionPolicy.RUNTIME)// 运行时有效
public @interface LoginRequired {
}
token生成,生成的token要能解析,解析出userId,这样方便到redis中取出校验
首先是依赖导入
io.jsonwebtoken
jjwt
0.9.0
public static String getToken(String userId){
String secret = "***";
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
SecretKey key = new SecretKeySpec(secret.getBytes(), "AES");
Date time = new Date();
JwtBuilder builder = Jwts.builder().setHeaderParam("typ", "JWT") // 设置header
.setHeaderParam("alg", "HS256").setIssuedAt(time) // 设置签发时间
//.setExpiration(new Date(time.getTime() + 1000 * 60 * 60))//设置token解析过期时间
.claim("userId", userId) // 设置内容
.setIssuer("***")// 设置签发人
.signWith(signatureAlgorithm, key); // 签名,需要算法和key
String jwt = builder.compact();
return jwt;
}
配置拦截器
public class LoginConfiguration implements WebMvcConfigurer {
@Autowired
private LoginInterceptor loginInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry ){
registry.addInterceptor(loginInterceptor);
WebMvcConfigurer.super.addInterceptors(registry);
}
}
实现HandlerInterceptor会有坑,jdki.8有个很神奇的东西,实现HandlerInterceptor不会让你重写类,也就没有preHandle,postHandle,afterCompletion.
ctrl+o 就可以啦
public class LoginInterceptor implements HandlerInterceptor {
@Autowired
RedisUtil redisUtil;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
// 如果不是映射到方法直接通过
if (!(handler instanceof HandlerMethod)) {
return true;
}
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
//判断接口是否需要登录
LoginRequired methodAnnotation = method.getAnnotation(LoginRequired.class);
// 有 @LoginRequired 注解,需要认证
if (methodAnnotation != null) {
//获取token
String token = request.getHeader("token");
if(token==null){
System.out.println("请重新登录");
return false;
}
//拿到token中的userId,从redis中获取token,校验前端请求头中的token
String secret = "didong";
SecretKey key = new SecretKeySpec(secret.getBytes(), "AES");
Claims claims;
try {
claims = Jwts.parser()
.setSigningKey(key)
.parseClaimsJws(token)
.getBody();
} catch (Exception e) {
System.out.println("不能相信签名: {}" + e);
claims = null;
}
String userId = (String) claims.get("userId");
String iToken = (String) redisUtil.get("token:"+userId, 0);
if (!iToken.equals(token)) {
System.out.println("token验证失败");
return false;
}
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
RedisUtil 类在我的文章中有提供