springboot如何优雅写登陆拦截器
上篇讲了登陆一些基础代码,也说到,没有拦截器的登陆不是完整的登陆,所以这篇讲如何优雅写登陆拦截器
需要两个:拦截器和拦截适配器
其中,
拦截器需要实现HandlerInterceptor,并实现preHandle方法
适配器需要实现WebMvcConfigurer,并实现addInterceptors方法
拦截器通常放在intercepter包下面,拦截适配器通常放在config包下面
首先preHandle方法
入参(实现的时候自动会带):HttpServletRequest、HttpServletResponse、Object
1、从request的header中拿到token
判断:token是否为null或是否为空。如果是,打印出错误码(code)和错误信息(message)。可返回“登陆失效,请重新登陆”------token为空,并返回false
2、解析传入的token,得到后台userid
判断:userid是否为空。如果是,打印出错误码(code)和错误信息(message)。可返回“令牌无效,请重新登录”------token无效:有值但是解析失败,并返回false
3、获取redis中的token
判断:redis中的token是否为null或者redis中的token是否不等于传过来的token,打印出错误码(code)和错误信息(message)。可返回“您已在别处登录”------token过期:解析成功,但是和redis不一致,并返回false
4、返回true
代码在此
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { String token = request.getHeader("token"); //判断是否有传token if (token == null || "".equals(token)) { System.out.print("code="+4000+"message=token为空") return false; } //解析传入的token,获得后台user_id String userId = JwtToken.getUserId(token);// 这个上篇文章讲过 if (userId == null) { System.out.print("code="+4001+"message=token无效:有值但是解析失败") return false; } //获取redis中的token String redisTokenKey = String.format(GODZILLA:ADMIN:TOKEN:%s, userId); String redisToken = (String) redisTemplate.opsForValue().get(redisTokenKey); if (redisToken == null || !redisToken.equals(token)) { System.out.print("code="+4002+"message=token过期:解析成功,但是和redis不一致") return false; } return true; }
然后addInterceptors方法
入参:InterceptorRegistry
1、首先类中生成前台和后台用户的拦截器对象
2、然后重写addInterceptors方法
话不多说,直接上代码
@Bean public AAALoginInterceptor getAAALoginInterceptor() { // 这个对应自己的拦截器就ok return new AAALoginInterceptor(); } @Bean public BBBLoginInterceptor getBBBLoginInterceptor() { return new BBBLoginInterceptor(); }
public void addInterceptors(InterceptorRegistry registry) { // 前台登录用户拦截器 registry.addInterceptor(getAAALoginInterceptor()) // 添加拦截器(这个拦截器是getAAALoginInterceptor这个方法的返回,即getAAALoginInterceptor对象) .addPathPatterns("/**")// 拦截所有url .excludePathPatterns(getCommonExcludePath()) // 除了getCommonExcludePath这个方法中返回的路径 .excludePathPatterns(getFrontExcludePath());// 除了getFrontExcludePath这个方法中返回的路径 // 后台登录用户拦截器 registry.addInterceptor(getBBBLoginInterceptor()) .addPathPatterns("/**") .excludePathPatterns(getCommonExcludePath()) .excludePathPatterns(getAdminExcludePath()); }
/** * 统一跳过验证的Path * @return */ private List<String> getCommonExcludePath() { List<String> list = new ArrayList<>(); list.add("/error");// 以error开头的所有url list.add("/swagger-resources/**");//swagger-resources开头的 url list.add("/swagger-ui.html/**");// 以swagger-ui.html开头的所有url return list; }
private List<String> getBBBExcludePath() { List<String> list = new ArrayList<>(); list.add("/aaa/**");// 以aaa开头的所有url list.add("/bbb/**"); //以bbbf开头的所有url//todo list.add("/bbb/login");// 密码/验证码登录接口 // 以/bbb/login开头的所有url list.add("/bbb/code");// 后台获取验证码 // 以/bbb/code开头的所有url return list; }
下面的代码同理
private List<String> getAAAExcludePath() { List<String> list = new ArrayList<>(); list.add("/bbb/**"); list.add("/aaa/**"); list.add("/aaa/login");//密码登录接口 list.add("/aaa/user/verify_code");//验证码登录 list.add("/aaa/send_vcode");//发送验证码 return list; }
补充一个坑哈:
前端在调试登陆接口的时候用token直接登陆,爆出了跨域的错误,后来经排查,我们项目中有用到两个token,一个AAAtoken,一个BBBtoken(我的这个是BBBtoken),跨域只放行了AAAtoken,这时候需要加上BBBtoken才可以
response.setHeader("Access-Control-Allow-Headers", "Origin,AAAtoken,BBBToken,x-requested-with,Content-Type,Accept");
类似于这样
- 说得太好了!Spring Boot如何实现过滤器、拦截器与切片?
- spring boot如何添加拦截器
- 如何优雅的使用springboot项目内置tomcat
- 如何在SpringBoot中配置拦截器,实现登录拦截?
- SpringBoot中如何优雅的读取yml配置文件?
- springboot(六):如何优雅的使用mybatis
- Spring Boot 优雅的配置拦截器方式
- Java微服务——如何优雅关闭 Spring Boot 应用
- Spring Boot系列(六):如何优雅的使用mybatis
- springboot项目中定时任务如何优雅退出
- Spring Boot 2.X 如何优雅的解决跨域问题?
- SpringBoot (六) :如何优雅的使用 mybatis
- spring boot之如何优雅的使用mybatis
- spring boot如何使用spring AOP实现拦截器
- Spring Boot 优雅的配置拦截器方式
- SpringBoot如何优雅的将静态资源配置注入到工具类中
- 如何优雅的抛出Spring Boot注解的异常详解
- 如何优雅的关闭基于Spring Boot 内嵌 Tomcat 的 Web 应用
- spring boot(六):如何优雅的使用mybatis
- Spring Boot项目中如何定制拦截器