为什么需要拦截器?
在我们开发的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 项目结构
2.3 类的分析
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
4.2 访问个人路径:http://127.0.0.1:9000/user/getUserInfo
带上需要的参数再次访问:
4.3 访问隐私路径:
带上参数和请求头再次访问:
测试成功!
今天的表演到此结束咯~