一文搞懂Spring Boot自定义拦截器

为什么需要拦截器?

在我们开发的Web系统中,资源可分为大致三类:公开资源个人资源隐私资源,比如公开资源有任何人都能看新闻、视频、文章等等,个人资源就是指系统用户的个人信息等等,隐私资源可以表示系统的后台管理、用户管理等等。

因此我们需要进行系统用户访问资源的认证规则,而Spring自带的拦截器处理器就可以很好地完成我们的需求,下面开始今天的表演!

1 场景需求分析

我们假设有三类资源,分别为公开资源个人资源隐私资源,请求路径分别对应为:

  • 公开资源:/user/getUserPublicInfo
  • 个人资源:/user/getUserInfo
  • 隐私资源:/user/getUserPrivateInfo

此外我们还需要一个别拦截后的跳转路径,防止用户在自己被拦截后还浑然不知

  • 未授权下跳转路径:/user/noAuth

下面我们罗列下访问这些资源都有什么要求

资源名称

资源路径

要求

公开资源

/user/getUserPublicInfo

个人资源

/user/getUserInfo

带上请求参数token

隐私资源

/user/getUserPrivateInfo

带上请求参数token加请求头ymx-name

2 项目架构

2.1 依赖和配置文件

我们新建Spring Boot项目,引入依赖,修改配置文件

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>

配置文件:

server.port=9000

2.2 项目结构

一文搞懂Spring Boot自定义拦截器_mvc

2.3 类的分析

一文搞懂Spring Boot自定义拦截器_spring_02

3 具体代码实现

3.1 项目代码实现

UserController.java

/**
* @desc: UserController
* @author: YanMingXin
* @create: 2021/9/27-17:12
**/
@RestController
@RequestMapping("/user")
public class UserController {

@Data
@Accessors(chain = true)
class User {
private String name;
private Integer age;
}

/**
* 个人资源
*
* @return
*/
@RequestMapping("/getUserInfo")
public User getUserInfo() {
return new User().setName("User:zs").setAge(12);
}

/**
* 隐私资源
*
* @return
*/
@RequestMapping("/getUserPrivateInfo")
public User getUserPrivateInfo() {
return new User().setName("PrivateUser:ls").setAge(2);
}

/**
* 公开资源
*
* @return
*/
@RequestMapping("/getUserPublicInfo")
public User getUserPublicInfo() {
return new User().setName("PublicUser:ww").setAge(15);
}

/**
* 未授权跳转页面
*
* @return
*/
@RequestMapping("/noAuth")
public String noAuth() {
return "You were intercepted~";
}
}

WebInterceptorHandler.java

/**
* @desc: 自定义拦截器
* @author: YanMingXin
* @create: 2021/9/27-17:10
**/
@Component
public class WebInterceptorHandler implements HandlerInterceptor {

private final String USER_TOKEN_NAME = "token";

private final String USER_TOKEN_VALUE = "ymx";

private final String AUTH_HEADER = "ymx-name";

private final String PRIVATE_URL = "/user/getUserPrivateInfo";

private final String REDIRECT_URL = "/user/noAuth";

/**
* 预处理回调方法
*
* @param request
* @param response
* @param handler
* @return 返回true为继续处理,false为中断处理
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String token = request.getParameter(USER_TOKEN_NAME);
String headerValue = request.getHeader(AUTH_HEADER);
String requestURI = request.getRequestURI();
//用户个人隐私
if (PRIVATE_URL.equals(requestURI)) {
if (USER_TOKEN_VALUE.equals(headerValue) && USER_TOKEN_VALUE.equals(token)) {
return true;
} else {
//拦截后跳转路径
response.sendRedirect(REDIRECT_URL);
return false;
}
}
//一般隐私
if (USER_TOKEN_VALUE.equals(token)) {
return true;
}
//拦截后跳转路径
response.sendRedirect(REDIRECT_URL);
return false;
}

/**
* 后处理回调方法,在渲染视图之前实现处理器的后处理
*
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}

/**
* 整个请求处理完毕回调方法,即在视图渲染完毕时回调,可用于记录日志
*
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

}
}

WebInterceptorConfig.java

/**
* @desc: 拦截器配置
* @author: YanMingXin
* @create: 2021/9/27-17:01
**/
@Configuration
public class WebInterceptorConfig extends WebMvcConfigurationSupport {

/**
* 注入自定义拦截器
*/
@Resource
private WebInterceptorHandler webInterceptorHandler;

/**
* 配置拦截器和拦截、放行路径
*
* @param registry
*/
@Override
protected void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(webInterceptorHandler)
.excludePathPatterns("/user/getUserPublicInfo")
.excludePathPatterns("/user/noAuth")
.addPathPatterns("/**");
}
}

3.2 总体分析

实现自定义拦截器:

在Spring5之前

@Component
public class WebInterceptorHandler extends WebMvcConfigurerAdapter {}

Spring5及以后

@Component
public class WebInterceptorHandler implements HandlerInterceptor {}

@Component
public class WebInterceptorHandler extends WebMvcConfigurationSupport {}

拦截器配置:

@Configuration
public class WebInterceptorConfig extends WebMvcConfigurationSupport{}

4 测试

启动项目,打开postman

4.1 访问公开路径:http://127.0.0.1:9000/user/getUserPublicInfo

一文搞懂Spring Boot自定义拦截器_拦截器_03

4.2 访问个人路径:http://127.0.0.1:9000/user/getUserInfo

一文搞懂Spring Boot自定义拦截器_spring_04

带上需要的参数再次访问:

一文搞懂Spring Boot自定义拦截器_mvc_05

4.3 访问隐私路径:

一文搞懂Spring Boot自定义拦截器_mvc_06

带上参数和请求头再次访问:

一文搞懂Spring Boot自定义拦截器_拦截器_07

测试成功!

今天的表演到此结束咯~