• 预防Dos攻击


    Dos----拒绝服务攻击,一般是构造特殊的输入,使得后台的处理耗时远超正常水平,随着请求越来越多,后台服务越发疲于奔命,最后因资源耗尽,无法再接受新的请求,最终造成拒绝服务的效果。

    特殊输入例如:
    分页查询时传一个很大的pageSize;
    入参是一个很大的集合。

    对于前者,做一个公共函数检查pageSize的大小,确定合理的范围即可。
    对于后者,往往是在post请求里,可以做一个filter来处理所有的incoming request。参考了一些资料,样例代码如下:

    @Component
    public class BodySizeLimitFilter implements Filter {
    
        private static final List<String> METHODS_WITH_BODY = Collections.unmodifiableList(
            Arrays.asList("POST", "PUT", "OPTIONS", "DELETE", "PATCH"));
    
        private static final String CONTENT_LENGTH_HEADER = "Content-Length";
    
        private static final int TOO_LARGE_STATUS = 413;
    
        @Value("${reqbody.maxsize:4096}")
        private long contentLengthLimit;
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
            HttpServletRequest httpServletRequest = (HttpServletRequest) request;
            HttpServletResponse httpResponse = (HttpServletResponse) response;
    
            if (!METHODS_WITH_BODY.contains(httpServletRequest.getMethod())) {
                chain.doFilter(httpServletRequest, httpResponse);
                return;
            }
    
            long contentSize = getContentLength(httpServletRequest);
    
            if (contentSize > contentLengthLimit) {
                resetRespAndSetStatus(httpResponse, TOO_LARGE_STATUS);
            } else {
                chain.doFilter(request, response);
            }
        }
    
        private void resetRespAndSetStatus(HttpServletResponse response, int status) {
            response.reset();
            response.setStatus(status);
        }
    
        private long getContentLength(HttpServletRequest httpRequest) {
            String contentLength = httpRequest.getHeader(CONTENT_LENGTH_HEADER);
            return safeToLong(contentLength, 0);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    不过,考虑到content-length也是可以被篡改的,还是要在rest入口处做一下集合长度的校验。这里可使用springboot的@Valid注解。
    对于前端POST调用传过来的requestBody参数,在函数声明里用jaxrs规范的@Valid注解处理,比如:

    @Path("/test")
    @Consumes({ "application/json;charset=UTF-8" })
    @Named
    public class TestRestService {
    
        @POST
        @Path("/hello")
        @Consumes({ "application/json" })
        @Produces({ "application/json" })
        public ServiceResponse<String> test(@Valid TestParam testParam) {
            throw new BaseException("i18n.test.example");
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    同时,在TestParam数据类里用@Size等注解标记要校验的字段:

    @Data
    public class TestParam {
        @Size(max = 10, min = 2, message = "[strs]size between 2~10")
        private List<String> strs;
    
        @Size(max = 6, min = 1, message = "[singleStr]length between 1~6")
        private String singleStr;
    
        @Min(value = 0)
        @Max(value = 1)
        private int num;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    这样spring框架就会自动为我们检查TestParam成员中list类型的长度、整型的大小、字符串类型的长度等。一旦有错误,就会抛出ConstraintViolationException异常,我们设法截获该异常,将错误信息填到Response中,给前台展示。
    顺带说一下,校验时,spring controller类上的@Validated注解其实可以不要的。若调用内部spring bean时需做参数校验,则必须在spring bean的类定义上加@Validated注解(@Valid注解不能用于类),然后再在要校验的方法参数前加@Valid等注解。
    对于GET调用的参数,校验起来更为简单,直接用@Size等注解修饰函数参数即可:

        @GET
        @Path("/helloPrimitive")
        @Consumes({ "application/json" })
        @Produces({ "application/json" })
        public ServiceResponse<String> testPrimitive(@QueryParam("id") @Max(value = 10) int id,
            @QueryParam("desc") @Size(max=15) String desc) {
            throw new BaseException("i18n.test.example");
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
  • 相关阅读:
    【1day】H5S视频平台未授权漏洞学习
    java计算机毕业设计五金机电市场批发零售管理信息系统源程序+mysql+系统+lw文档+远程调试
    SpringBoot生成Excel文件并下载到浏览器
    Java Number & Math 类
    【计算机组成原理】第六章 总线
    OpenVPN安装部署详解
    WPF布局控件之DockPanel布局
    【Git】一起来了解一下版本控制系统吧
    基于云平台的智能变电站远程监控系统
    mysql group_concat 与 union 联合查询漏洞,数据列最大长度为341
  • 原文地址:https://blog.csdn.net/tlxamulet/article/details/132811877