SpringBoot 中注解方式的拦截过滤
使用场景
公司运行的App 登陆-验证码短信接口,遭到大量的恶意攻击。处于安全的考虑,需要客户端api目前的一些接口加上验证签名的功能,以提高安全性。
现行的App之前也有过签名的秘钥在,后来出于性能考虑,验签功能并没有用上。所以并不是所有的接口都需要验签,只需要要在需要的接口及时加入验签功能即可。
实现步骤
我们运行的api项目,是基于Spring Cloud的一个项目,所以都是基于Spring Boot 的,版本是1.5.3
1.先定义一个注解,我们只需要对需要验签的接口加上注解即可。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface Signature {
  String value() default "";
}
2.再写一个扩展org.springframework.web.servlet.handler.HandlerInterceptorAdapter的拦截器 SignatureInterceptor
这里我们只需要重写前置拦截的方法即可
public class SignatureInterceptor extends HandlerInterceptorAdapter {
    private final static Logger logger = LoggerFactory.getLogger(SignatureInterceptor.class);
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
                             Object handler) throws Exception {
        if (handler instanceof HandlerMethod) {
            HandlerMethod hm = (HandlerMethod) handler;
            Signature signature = hm.getMethodAnnotation(Signature.class);
            if (signature == null) {
                return true;
            }
            //验证签名的方法
            ApiError result = checkSigature(request, response);
            if (result == null) {
                return true;
            }
            SimpleResponse simResponse = new SimpleResponse(result, request.getRequestURI());
            String strResponseJson = JsonUtil.toJson(simResponse);
            response.setContentType("application/json;charset=UTF-8");
            try (OutputStream out = response.getOutputStream()) {
                out.write(strResponseJson.getBytes("UTF-8"));
                out.flush();
            }
            request.setAttribute(Constants.RESPONSE_BODY_STRING, strResponseJson);
            return false;
        }
        return super.preHandle(request, response, handler);
    }
3. 把这个拦截器加入到配置类中
@Configuration
public class WebMvcConfiguration extends WebMvcConfigurerAdapter{
    @Bean
    @Autowired
    public ServletRegistrationBean dispatcherRegistration(DispatcherServlet dispatcherServlet){
        ServletRegistrationBean dispatcherRegistration = new ServletRegistrationBean(dispatcherServlet);
        dispatcherRegistration.addUrlMappings("*.do");
        dispatcherRegistration.addUrlMappings("*.htm");
        dispatcherRegistration.addUrlMappings("/*");
        dispatcherRegistration.setLoadOnStartup(1);
        return dispatcherRegistration;
    }
    /**
     *  通过 @Bean 注入这个 拦截器
     * @return
     */
    @Bean
    public HandlerInterceptor signatureInterceptor(){
        return new SignatureInterceptor();
    }
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // signatureInterceptor 定义 拦截的URL 的类型
        registry.addInterceptor(signatureInterceptor()).addPathPatterns("/**")
                .excludePathPatterns("/dss/**")
                .excludePathPatterns("/mappings","/trace","/info","/metrics","/health","/env","/refresh","/configprops")
                .excludePathPatterns("/archaius","/proxy.stream","/hystrix","/hystrix/**","/hystrix.stream")
                .excludePathPatterns("/heapdump","/dump")
                .excludePathPatterns("/error","/loggers","/loggers/**");
    }
    @Override
    public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
        AppExceptionResolver appExceptionResolver = new AppExceptionResolver();
        appExceptionResolver.setOrder(1);
        exceptionResolvers.add(appExceptionResolver);
    }
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        MMHFastjsonHttpMessageConverter messageConverter = new MMHFastjsonHttpMessageConverter();
        messageConverter.setSupportedMediaTypes(Lists.newArrayList(MediaType.APPLICATION_JSON_UTF8));
        messageConverter.setDefaultCharset(Charset.forName("UTF-8"));
        converters.add(messageConverter);
    }
    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
        configurer.favorPathExtension(false);
    }
}
4. 在需要验签的接口前加入注解@Signature
	@RequestMapping(value = {"/V2/sms/vcode/sendSmsVcodeForLoginOrReg.htm","/s/V2/sms/vcode/sendSmsVcodeForLoginOrReg.htm"})
	@Signature
	public void sendSmsVcodeForLoginOrRegV2() {
			responseSuccessJson(response);
	}
通过以上4部,再启动项目的时候,拦截器节开始了它的拦截功能,会针对添加了
@Signature的接口,运行前置拦截功能,验签通过才执行接口本来的业务逻辑。
源码分析
本段代码的核心是HandlerInterceptorAdapter这个类,拦截适配器 它提供了4个方法:
- preHandle 预处理,该方法将在请求处理之前进行调用
- postHandle 后置处理, 该方法将在请求处理之后,DispatcherServlet进行视图返回渲染之前进行调用
- afterCompletion 在请求后处理,并在DispatcherServlet进行视图返回渲染之后调用
可以参考看https://blog.csdn.net/qq_35246620/article/details/68487904?1491374806898
SpringBoot 中注解方式的拦截过滤的更多相关文章
- Springboot中注解@Configuration源码分析
		Springboot中注解@Configuration和@Component的区别 1.先说结论,@Configuration注解上面有@Component注解,所以@Component有的功能@Co ... 
- springboot中使用过滤器、拦截器、监听器
		监听器:listener是servlet规范中定义的一种特殊类.用于监听servletContext.HttpSession和servletRequest等域对象的创建和销毁事件.监听域对象的属性发生 ... 
- SpringMVC的controller方法中注解方式传List参数使用@RequestBody
		在SpringMVC控制器方法中使用注解方式传List类型的参数时,要使用@RequestBody注解而不是@RequestParam注解: //创建文件夹 @RequestMapping(value ... 
- 在ssh框架中注解方式需要注意的几个问题
		1.注解方式的时候 Spring 2.5 引入了 @Autowired 注释,它可以对类成员变量.方法及构造函数进行标注,完成自动装配的工作. 通过 @Autowired的使用来消除 set ,get ... 
- Springboot中静态资源和拦截器处理(踩了坑)
		背景: 在项目中我使用了自定义的Filter 这时候过滤了很多路径,当然对静态资源我是直接放过去的,但是,还是出现了静态资源没办法访问到springboot默认的文件夹中得文件 说下默认映射的文件夹有 ... 
- SpringBoot使用注解方式整合Redis
		1.首先导入使用Maven导入jar包 <dependency> <groupId>org.springframework.boot</groupId> <a ... 
- SpringBoot | 问题 | 注解方式下无法发现Bean
		在排除注解的问题后,考虑扫描类的位置, [SpringBoot项目的Bean装配默认规则是根据Application类所在的包位置从上往下扫描! “Application类”是指SpringBoot项 ... 
- Spring中注解方式实现IOC和AOP
		1.IOC注解 1.1 IOC和DI的注解 IOC: @Component:实现Bean组件的定义 @Repository:用于标注DAO类,功能与@Component作用相当 @Service:用 ... 
- SpringBoot系列-整合Mybatis(注解方式)
		目录 一.常用注解说明 二.实战 三.测试 四.注意事项 上一篇文章<SpringBoot系列-整合Mybatis(XML配置方式)>介绍了XML配置方式整合的过程,本文介绍下Spring ... 
随机推荐
- Kubernetes学习笔记(二):Pod、标签、注解
			pod与容器 一个pod是一组紧密相关的容器,它们总是一起运行在同一个节点上,以及同一个LInux命名空间中. 每个pod拥有自己的ip,包含若干个容器.pod分布在不同的节点上. 为什么需要pod ... 
- nginx配置之错误和访问日志功能
			错误日志功能:logs/error.log nginx.conf中: #error_log logs/error.log; #error_log logs/error.log notice; #err ... 
- Django之请求生命周期
			settings.py中间件执行 自定义中间件的配置: (1)任意新建一个py文件,导入模块from django.utils.deprecation import MiddlewareMixin ( ... 
- etcd分布式锁及事务
			前言 分布式锁是控制分布式系统之间同步访问共享资源的一种方式.在分布式系统中,常常需要协调他们的动作.如果不同的系统或是同一个系统的不同主机之间共享了一个或一组资源,那么访问这些资源的时候,往往需要互 ... 
- Aizu - 2224
			题目链接:https://vjudge.net/problem/Aizu-2224 题目大意: 先给出 N 个点的坐标(x,y),这N个点之间有且只有M条边,接下来给出 M 条边的两端点,每条边对应的 ... 
- POJ1905
			题目链接:http://poj.org/problem?id=1905 题目大意: 竹竿受热会膨胀.设其原长为 L ,受热膨胀后的长度 L'=(1+n*C)*L ,其中 n, C, L都是要输入的参数 ... 
- 【Mac 实用技巧】不定期更新
			Mac去掉截屏图片边框外阴影效果 一次命令行:defaults write com.apple.screencapture disable-shadow -bool true;\killall Sys ... 
- Java——DOS命令窗口用命令编译文件夹下所有.java文件
			1.进入指定目录 cd 进入用户主目录 cd ~ 进入用户主目录 cd - 返回进入此目录之前所在的目录 cd .. 返回上级目录 cd\ 直接退回到当前盘根目录2. ... 
- thymeleaf抛出项目上下文ServletContext ,session,request等信息
			@RequestMapping("/alls") public String allsinfo(HttpSession session, HttpServletRequest re ... 
- css3,transition,animation两种动画实现区别
			我们为页面设置动画时,往往会用到transition还有animation以及transfrom属性或者用到js. 其实通常情况下,对于使用js我们更加倾向于使用css来设置动画. transfrom ... 
