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

举报
海风极客 发表于 2022/10/16 19:06:29 2022/10/16
【摘要】 一文搞懂Spring Boot自定义拦截器 为什么需要拦截器?在我们开发的Web系统中,资源可分为大致三类:公开资源、个人资源和隐私资源,比如公开资源有任何人都能看新闻、视频、文章等等,个人资源就是指系统用户的个人信息等等,隐私资源可以表示系统的后台管理、用户管理等等。因此我们需要进行系统用户访问资源的认证规则,而Spring自带的拦截器处理器就可以很好地完成我们的需求,下面开始今天的表演...

一文搞懂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 项目结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1o8OoYIy-1632796828007)(一文搞懂Spring Boot自定义拦截器.assets/image-20210928103228776.png)]

2.3 类的分析

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GuNFDZKq-1632796828009)(一文搞懂Spring Boot自定义拦截器.assets/image-20210928102537477.png)]

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0usbDvJz-1632796828011)(一文搞懂Spring Boot自定义拦截器.assets/image-20210928103347665.png)]

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zPinn2tP-1632796828013)(一文搞懂Spring Boot自定义拦截器.assets/image-20210928103410257.png)]

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UuOjmKZV-1632796828015)(一文搞懂Spring Boot自定义拦截器.assets/image-20210928103506420.png)]

4.3 访问隐私路径:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8jdS1XC8-1632796828016)(一文搞懂Spring Boot自定义拦截器.assets/image-20210928103528767.png)]

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Rwr3BG4d-1632796828018)(一文搞懂Spring Boot自定义拦截器.assets/image-20210928103607515.png)]

测试成功!

今天的表演到此结束咯~

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。