Spring Boot中使用拦截器
登录拦截器,防止绕过登录,通过已知路径直接访问页面。
1.1 定义拦截器 定义拦截器
只需要实现 HandlerInterceptor 接口, HandlerInterceptor 接口是所有自定义拦截 器或者 Spring Boot 提供的拦截器的鼻祖。该接口中有三个方法: preHandle(……) 、 postHandle(……) 和 afterCompletion(……) 。
preHandle(……) 方法:该方法的执行时机是,当某个 url 已经匹配到对应的 Controller 中的某 个方法,且在这个方法执行之前。所以 preHandle(……) 方法可以决定是否将请求放行,这是通 过返回值来决定的,返回 true 则放行,返回 false 则不会向后执行。
postHandle(……) 方法:该方法的执行时机是,当某个 url 已经匹配到对应的 Controller 中的某 个方法,且在执行完了该方法,但是在 DispatcherServlet 视图渲染之前。所以在这个方法中有 个 ModelAndView 参数,可以在此做一些修改动作。
afterCompletion(……) 方法:顾名思义,该方法是在整个请求处理完成后(包括视图渲染)执 行,这时做一些资源的清理工作,这个方法只有在 preHandle(……) 被成功执行后并且返回 true 才会被执行。 了解了该接口,接下来自定义一个拦截器。
1 package com.tan.interceptor; 2 import org.springframework.web.servlet.HandlerInterceptor; 3 import javax.servlet.http.HttpServletRequest; 4 import javax.servlet.http.HttpServletResponse; 5 6 /** 7 * @description: 8 * @author: 85726 9 * @time: 2021/1/25 19:58 10 */ 11 public class LoginInterceptor implements HandlerInterceptor { 12 13 /** 14 * 登录拦截器,防止未登录就直接通过路径访问页面 15 */ 16 @Override 17 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 18 if (request.getSession().getAttribute("user") == null) { 19 response.sendRedirect("/admin"); 20 return false; 21 } 22 return true; 23 } 24 }
1.2 配置拦截器
方式一:继承 WebMvcConfigurationSupport类 ,然后重写 addInterceptors 方法,将自定义的拦截器添加进去即可
1 @Configuration 2 public class MyInterceptorConfig extends WebMvcConfigurationSupport { 3 @Override 4 protected void addInterceptors(InterceptorRegistry registry) { 5 registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**"); 6 super.addInterceptors(registry); 7 } 8 }
在该配置中重写 addInterceptors 方法,将上面自定义的拦截器添加进去, addPathPatterns
方法是添加要拦截的请求,这里拦截所有的请求。
如果使用上面这种配置的话,会发现一个缺陷,那就是静态资源被拦截了。可以在 resources/static/ 目录下放置一个图
片资源或者 html 文件,然后启动项目直接访问,即可看到无法访问的现象。WebMvcConfigurationSupport 会导致默认的静态资源被拦截,这就需要我们手动将静态资源放
开。如何放开呢?除了在 MyInterceptorConfig 配置类中重写 addInterceptors 方法外,还需要再重写一
个方法: addResourceHandlers ,将静态资源放开:
/** * 用来指定静态资源不被拦截,否则继承WebMvcConfigurationSupport这种方式会导致静态资源无法 直接访问 * @param registry */ @Override protected void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/**").addResourceLocations("classpath:/static/"); super.addResourceHandlers(registry); }
这样配置好之后,重启项目,静态资源也可以正常访问了。
方式二:
不继承 WebMvcConfigurationSupport 类,直接实现 WebMvcConfigurer 接口,然后重写
addInterceptors 方法,将自定义的拦截器添加进去即可,如下
package com.tan.interceptor; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; /** * @description: * @author: 85726 * @time: 2021/1/25 20:06 */ @Configuration public class WebConfig implements WebMvcConfigurer { /** *拦截 addPathPatterns("/admin/**") 未登录就想访问admin下的页面 *放行 excludePathPatterns("/admin") * 或 excludePathPatterns("/admin/login"); 此处是登录页面,放行 * */ @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/admin/**").excludePathPatterns("/admin") .excludePathPatterns("/admin/login"); } }
实现 WebMvcConfigure 接口的话,不会拦截 Spring Boot 默认的静态资源
两种方式比较:
这两种方式都可以,具体他们之间的细节,感兴趣的可以做进一步的研究,由于这两种方式的不
同,继承 WebMvcConfigurationSupport 类的方式可以用在前后端分离的项目中,后台不需要访问静
态资源(就不需要放开静态资源了);实现 WebMvcConfigure 接口的方式可以用在非前后端分离的项
目中,因为需要读取一些图片、css、js文件等等。