自定义登录拦截,token验证
1.需求
我们公司中,老项目是用老框架写的,想要在老的项目中加入新的功能模块,但是不能盲目的加模块代码,因为需要校验用户的登录信息等。在之前的一个项目中我用springsecurity框架写过类似的功能,但是直接copy进来这样太重了,而且代码太繁琐,所以我就自己写了个自定义的拦截器。
2.自定义拦截器的配置
1.实现HandlerInterceptor接口,重写preHandle方法。
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 获取token 因为之前的老项目是通过token验证的
String token=(String) request.getHeader("token");
// 打印下url看下
String url=request.getRequestURI();
System.out.println(url);
// 如果 token 不为空 通过redis去查询
if( !StringUtils.isEmpty(token)) {
// 通过redis查询登录id
String customerId = CustomerUtils.getCustomerIdByToken(token);
if (StringUtils.isEmpty(customerId)){
// 返回的 id为空 证明未登录,返回给前端json格式的数据
response.setContentType("application/json;charset=utf-8");
PrintWriter out = response.getWriter();
out.write("500");
out.close();
response.flushBuffer();
return false;
}
// 验证登录用户成功 允许访问对应的请求
return HandlerInterceptor.super.preHandle(request, response, handler);
}else { // 登录失败
response.setContentType("application/json;charset=utf-8");
PrintWriter out = response.getWriter();
out.write("500");
out.close();
response.flushBuffer();
return false;
}
}
}
2.将该拦截器注入到IOC容器中。
@Configuration
public class WebLoginConfig implements WebMvcConfigurer{
/**
* 注意:一定要把 登录拦截 bean 先注入到ioc中 要不然 在LoginInterceptor 中注入redis的bean就会报错
* @author gc
* @date 2020/7/7 15:43
* @param
* @return
*/
@Bean
LoginInterceptor localInterceptor() {
return new LoginInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 注册需要拦截的请求 拦截该项目下所有的请求
registry.addInterceptor(localInterceptor()).addPathPatterns("/**");
WebMvcConfigurer.super.addInterceptors(registry);
}
}
3.加入拦截器中redis查询id的工具类
@Component
public class CustomerUtils {
@Autowired
private RedisTemplate<String, byte[]> nxcloudRedisTemplate;
private static RedisTemplate<String, byte[]> redisTemplate;
// 解决静态方法用到注入的bean 空指针问题
@PostConstruct // 该注解 是 在servlet之前执行
public void init(){
redisTemplate = nxcloudRedisTemplate;
}
// 老项目中 存到redis中的用户id 经过序列化的 以下是解决 序列化问题 不使用其他
public static String getCustomerIdByToken(String token){
byte[] bytes = redisTemplate.opsForValue().get(token); // redis中查 用户id
if (bytes == null){
return null;
}
Object cusId = ByteToString.valueFromBytes(bytes); // 反序列化
return cusId+"";
}
}
说下@PostConstruct 注解
: 该注解 是 在项目启动 加载servlet的时候 加载的,就是项目启动的时候,该方法执行,并且只执行一次。
执行顺序: 构造方法 > @Autowired > @PostConstruct