• 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

  • 相关阅读:
    转换流--OutputStreamWriter类与InputStreamReader类
    Android getResources的作用和须要注意点
    sqlit使用要点之引入libsqlite3.dylib
    C语言文件操作之fgets()
    5款伊思儷超媒體繁体游戏 中文简体补丁
    memcpy的使用方法总结
    开发人员改变世界的初心
    expect
    HDU 1061 N^N (n的n次方的最后一位)
    linux杂谈(二十):apache服务配置
  • 原文地址:https://www.cnblogs.com/Profound/p/9010948.html
Copyright © 2020-2023  润新知