禁止不安全的HTTP请求

3,606 阅读2分钟

HTTP方法的不安全性

1、OPTIONS方法,将会造成服务器信息暴露,如中间件版本、支持的HTTP方法等。

2、PUT方法,由于PUT方法自身不带验证机制,利用PUT方法即可快捷简单地入侵服务器,上传Webshell或其他恶意文件,从而获取敏感数据或服务器权限。

3、DELETE方法,利用DELETE方法可以删除服务器上特定的资源文件,造成恶意攻击。

目前维护的项目是springboot项目,基于安全给项目添加配置文件,禁用springboot内置的tomcat 不安全的HTTP 请求.

添加配置文件即可

@Configuration
public class TomcatConfig {
    @Bean
    public TomcatServletWebServerFactory servletContainer() {
        TomcatServletWebServerFactory tomcatServletContainerFactory = new TomcatServletWebServerFactory();
        tomcatServletContainerFactory.addContextCustomizers(new TomcatContextCustomizer() {

            @Override
            public void customize(Context context) {
                SecurityConstraint constraint = new SecurityConstraint();
                SecurityCollection collection = new SecurityCollection();
                //http方法
                collection.addMethod("PUT");
                collection.addMethod("DELETE");
                collection.addMethod("HEAD");
                collection.addMethod("OPTIONS");
                collection.addMethod("PATCh");
                collection.addMethod("TRACE");
                //url匹配表达式
                collection.addPattern("/*");
                constraint.addCollection(collection);
                constraint.setAuthConstraint(true);
                context.addConstraint(constraint);
                //设置使用httpOnly
                context.setUseHttpOnly(true);

            }

        });
        return tomcatServletContainerFactory;
    }
}

那么问题了来了,项目中前端代码vue,调用接口会自动发送一个OPTIONS请求,而后台禁用了OPTIONS;报错403.

为什么会有OPTIONS请求

官方或者比较官方的定义:

HTTP 的 OPTIONS 方法 用于获取目的资源所支持的通信选项。客户端可以对特定的 URL 使用 OPTIONS 方法,也可以对整站(通过将 URL 设置为“*”)使用该方法。

官方文档没有理解,后来自己概括一句就是只要是非简单请求浏览器就会发出OPTIONS请求。用来:

1、获取服务器支持的HTTP请求方法;

2、用来检查服务器的性能。例如:AJAX进行跨域请求时的预检,需要向另外一个域名的资源发送一个HTTP OPTIONS请求头,用以判断实际发送的请求是否安全。

上面说到非简单请求,只要发出的是非简单请求就可以避免发出OPTIONS,查了一下简单请求与非简单请求:

简单请求与非简单请求

简单请求

  1. 你的方法(Method) 是 GET/HEAD/POST

  2. 你的请求头(header)没有自定义头

  3. 你的请求头(header)中的Content-Type字段的值是以下三种中的一种:

  • text/plain,

  • multipart/form-data,

  • application/x-www-form-urlencoded

同时满足,注意,是同时满足,才为简单请求,否则就是非简单请求

非简单请求中常见的情况(并不是全部情况)

  • 你的方法(Method) 是 PUT/DELETE 的 ajax 请求

  • 你的请求头(header)有自定义头

  • 你的请求头(header)中的Content-Type字段的值是application/json;charset=UTF-8

由于业务要求,前端添加了token和name 自定义请求。而后期修改代码代价太大。也就是不能从避免非简单请求的方法解决问题。

最后解决方案

在nginx中判断请求的请求类型,如果是OPTIONS类型return200.

结语

作为一个菜鸟程序员,大佬勿喷