使用场景

公司运行的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 中注解方式的拦截过滤的更多相关文章

  1. Springboot中注解@Configuration源码分析

    Springboot中注解@Configuration和@Component的区别 1.先说结论,@Configuration注解上面有@Component注解,所以@Component有的功能@Co ...

  2. springboot中使用过滤器、拦截器、监听器

    监听器:listener是servlet规范中定义的一种特殊类.用于监听servletContext.HttpSession和servletRequest等域对象的创建和销毁事件.监听域对象的属性发生 ...

  3. SpringMVC的controller方法中注解方式传List参数使用@RequestBody

    在SpringMVC控制器方法中使用注解方式传List类型的参数时,要使用@RequestBody注解而不是@RequestParam注解: //创建文件夹 @RequestMapping(value ...

  4. 在ssh框架中注解方式需要注意的几个问题

    1.注解方式的时候 Spring 2.5 引入了 @Autowired 注释,它可以对类成员变量.方法及构造函数进行标注,完成自动装配的工作. 通过 @Autowired的使用来消除 set ,get ...

  5. Springboot中静态资源和拦截器处理(踩了坑)

    背景: 在项目中我使用了自定义的Filter 这时候过滤了很多路径,当然对静态资源我是直接放过去的,但是,还是出现了静态资源没办法访问到springboot默认的文件夹中得文件 说下默认映射的文件夹有 ...

  6. SpringBoot使用注解方式整合Redis

    1.首先导入使用Maven导入jar包 <dependency> <groupId>org.springframework.boot</groupId> <a ...

  7. SpringBoot | 问题 | 注解方式下无法发现Bean

    在排除注解的问题后,考虑扫描类的位置, [SpringBoot项目的Bean装配默认规则是根据Application类所在的包位置从上往下扫描! “Application类”是指SpringBoot项 ...

  8. Spring中注解方式实现IOC和AOP

    1.IOC注解 1.1 IOC和DI的注解  IOC: @Component:实现Bean组件的定义 @Repository:用于标注DAO类,功能与@Component作用相当 @Service:用 ...

  9. SpringBoot系列-整合Mybatis(注解方式)

    目录 一.常用注解说明 二.实战 三.测试 四.注意事项 上一篇文章<SpringBoot系列-整合Mybatis(XML配置方式)>介绍了XML配置方式整合的过程,本文介绍下Spring ...

随机推荐

  1. Codeforces1157A(A题)Reachable Numbers

    A. Reachable Numbers Let's denote a function f(x)f(x) in such a way: we add 11 to xx, then, while th ...

  2. POJ1015

    题目链接:http://poj.org/problem?id=1015 大概题意: 法庭要挑选m人陪审团.先随机挑选n个公民,对于每个公民,控辩双方都有各自的“喜好度”p[ ] 和 d[ ],法庭要尽 ...

  3. 模板:DOM常用场景【表单提交】——javascript结合HTML DOM(或者JQuery)运用

    一.删除行为前的提示 首先要有一个onclick的DOM(点击)事件,和一个JavaScript弹出框:confirm()确认框 <script> function del(){ var ...

  4. Cube-UI组件中create-api 模块的基本使用

    1.这个模块的功能是什么? 官方文档是这样解释的: 该模块默认暴露出一个 createAPI 函数,可以实现以 API 的形式调用自定义组件.并且既可以在 Vue 实例上下文中调用,也可以在普通 js ...

  5. GO 使用Webhook 实现github 自动化部署

    通常大家开发大部分是本地git push 提交,服务器上git pull 手动更新.git 可以使用webhook实现自动部署.webhook是仓库平台的一个钩子事件,通过hook 钩子监听代码,回调 ...

  6. tp5增删改查基本操作

    //插入数据 $res = Db::execute('insert into phptab(info) values("小张")'); dump($res); //修改数据 $re ...

  7. 第4章 最基础的分类算法-k近邻算法

    思想极度简单 应用数学知识少 效果好(缺点?) 可以解释机器学习算法使用过程中的很多细节问题 更完整的刻画机器学习应用的流程 distances = [] for x_train in X_train ...

  8. SpringBoot入门系列(十二)统一日志收集

    前面介绍了Spring Boot 异常处理,不清楚的朋友可以看看之前的文章:https://www.cnblogs.com/zhangweizhong/category/1657780.html. 今 ...

  9. 3.key的操作

    我们之前使用Redis简单存储了三个参数: 在语句set name jack中,其中name就是一个key.我们Java中的变量名是有一定规则的,比如组成内容可以是“数字”,“字母”以及“下划线”. ...

  10. 计划任务工具-windows

    计划任务工具根据自己设定的具体时间,频率,命令等属性来规定所要执行的计划. 代码 # -*- coding: utf-8 -*- """ Module implement ...