spring boot 使用 HandlerInterceptor

简介: # 背景 在实际项目中,接口出于安全考虑,都会有验签的计算。目前接触的项目来看基本都是时间戳+干扰因子 然后md5计算的方式。现在学习,写一个简单demo, 其实如果不引入拦截器的话,验签计算全部在controller层实现也是可以的,但每个请求都需要去做一次计算,这种把公共功能的抽离,针对于所有请求前的判断,个人感觉有点切面的意思;   # DEMO 核心点: 1.

# 背景

在实际项目中,接口出于安全考虑,都会有验签的计算。目前接触的项目来看基本都是时间戳+干扰因子 然后md5计算的方式。现在学习,写一个简单demo,

其实如果不引入拦截器的话,验签计算全部在controller层实现也是可以的,但每个请求都需要去做一次计算,这种把公共功能的抽离,针对于所有请求前的判断,个人感觉有点切面的意思;

 

# DEMO

核心点:

1. controller层还是和原来的一模一样,不做修改

2. 创建一个ApiSignInterceptor 类 ,实现HandlerInterceptor 接口,完成 验签计算的核心代码;

3. 创建一个WebConfig类,继承WebMvcConfigurationSupport类,引入步骤2中创建的拦截器;

 

前言:

jdk8+spring boot2.0 版本 如果低版本些许不一致

 

show CODE

controller层:

@RestController
public class PeopleController {

    @GetMapping(value = "/1/people/{people_id}")
    public String getPeopleInfo(@PathVariable(value = "people_id", required = true) String peopleId) {
        return "hello world, this is people info of " + peopleId;
    }


    @GetMapping(value = "/2/people/{people_id}")
    public String getPeopleInfoV2(@PathVariable(value = "people_id", required = true) String peopleId) {
        return "hello THIS is v2 world, this is people info V2 of " + peopleId;
    }
}

没有任何变化,简单demo例子

 

拦截器,ApiSignInterceptor :

public class ApiSignInterceptor implements HandlerInterceptor {


    private final static String SEPERATOR = "_";
    private final static String SECRET = "jwentest";
    private final static String NO_PERMISSION_ERROR_MESSAGE = "Api Token Error, You have no permission to access this api";


    // md5计算
    private String md5Hex(String data) {
        return DigestUtils.md5Hex(data).toLowerCase();
    }

    private String getSign(String t) {
        return md5Hex(t + SEPERATOR + SECRET);
    }

    // sign计算,t为时间戳,sign为md5(t+"_"+"jwentest")

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        try {
            String t = request.getParameter("t");
            String sign = request.getParameter("sign");

            if (t.isEmpty() || sign.isEmpty()) {
                response.sendError(403, NO_PERMISSION_ERROR_MESSAGE);
                return false;
            }

            String expectedSign = getSign(t);

            if (!expectedSign.equals(sign)) {
                response.sendError(403, NO_PERMISSION_ERROR_MESSAGE);
                return false;
            }

        } catch (Throwable t) {
            response.sendError(403, NO_PERMISSION_ERROR_MESSAGE);
            return false;
        }

        return true;

    }

}

其中HandlerInterceptor 接口定义了三个方法,第一次看到我有点懵逼了,为啥接口定义的方法里面会有方法体呢,为什么可以不实现所有的方法了的,原因是JDK8中可以这样写了:

default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return true;
    }

    default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
    }

    default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
    }

本次我们使用到的是preHandle方法,三个方法的执行顺序如下:

preHandler -> Controller -> postHandler -> model渲染-> afterCompletion

因此可以在进入controller层之前拦截判断是否符合我们的安全要求;

 

使用,WebConfig 类:

@Configuration
public class WebConfig extends WebMvcConfigurationSupport {

    @Override
    protected void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new ApiSignInterceptor()).addPathPatterns("/1/people/**").excludePathPatterns("/2/people/**");
        super.addInterceptors(registry);
    }
}

这里是在项目引入拦截器,

@Configuration ,config形式加载在容器中

其中addPathPatterns 和 excludePathPatterns 方法,从方法名就可以看出来,是针对拦截器的范围控制,上面的代码就是针对/1/people/** 生效,对/2/people/**  不生效

 

目录结构如下:

 

虽千万人,吾往矣!
目录
相关文章
|
8月前
|
Java 应用服务中间件 Maven
SpringBoot 项目瘦身指南
SpringBoot 项目瘦身指南
170 0
|
8月前
SpringBoot+Mybatis-Plus+PageHelper分页+多条件查询
SpringBoot+Mybatis-Plus+PageHelper分页+多条件查询
205 0
|
2月前
|
存储 运维 安全
Spring运维之boot项目多环境(yaml 多文件 proerties)及分组管理与开发控制
通过以上措施,可以保证Spring Boot项目的配置管理在专业水准上,并且易于维护和管理,符合搜索引擎收录标准。
64 2
|
3月前
|
SQL JSON Java
mybatis使用三:springboot整合mybatis,使用PageHelper 进行分页操作,并整合swagger2。使用正规的开发模式:定义统一的数据返回格式和请求模块
这篇文章介绍了如何在Spring Boot项目中整合MyBatis和PageHelper进行分页操作,并且集成Swagger2来生成API文档,同时定义了统一的数据返回格式和请求模块。
115 1
mybatis使用三:springboot整合mybatis,使用PageHelper 进行分页操作,并整合swagger2。使用正规的开发模式:定义统一的数据返回格式和请求模块
|
3月前
|
缓存 NoSQL Java
Springboot自定义注解+aop实现redis自动清除缓存功能
通过上述步骤,我们不仅实现了一个高度灵活的缓存管理机制,还保证了代码的整洁与可维护性。自定义注解与AOP的结合,让缓存清除逻辑与业务逻辑分离,便于未来的扩展和修改。这种设计模式非常适合需要频繁更新缓存的应用场景,大大提高了开发效率和系统的响应速度。
100 2
|
7月前
|
运维 Java 关系型数据库
Spring运维之boot项目bean属性的绑定读取与校验
Spring运维之boot项目bean属性的绑定读取与校验
71 2
|
7月前
|
存储 运维 Java
Spring运维之boot项目开发关键之日志操作以及用文件记录日志
Spring运维之boot项目开发关键之日志操作以及用文件记录日志
80 2
|
7月前
|
Java Maven
springboot项目打jar包后,如何部署到服务器
springboot项目打jar包后,如何部署到服务器
465 1
|
7月前
|
XML 运维 Java
Spring运维之boot项目打包jar和插件运行并且设置启动时临时属性和自定义配置文件
Spring运维之boot项目打包jar和插件运行并且设置启动时临时属性和自定义配置文件
66 1
|
7月前
springboot2.4.5使用pagehelper分页插件
springboot2.4.5使用pagehelper分页插件
203 0