1. 背景说明

Web安全测试中,会要求屏蔽非必要的不安全Http请求方法。一般要求保留get和post,其他的方法一般屏蔽,比如:OPTIONS,DELETE等。

本文主要收集业务系统中,不同时期,我们框架的各版本的处理方案,都基于tomcat+spring各版本体系。

2. 解决思路

使用tomcat自带的安全认证机制。配置对应的URL下的http方法访问都需要认证,但不配置认证方式,以实现对不安全的http方法的控制访问。主要应用的配置,原理上通过web.xml中的security-constraint节点进行定义。

具体相关参数的配置说明如下:

  • web-resource-collection:此元素确定应该保护的资源。包含几个特定的子元素:
  • url-pattern:表示受控的URL路径。
  • http-method:表示受控的http请求方法。例如:OPTIONS
  • http-method-omission:表示忽悠受控的http请求方法
  • auth-constraint:指出哪些用户应该具有受保护资源的访问权,正常情况应该包含一个或多个标识具有访问权限的用户类别role-name元素。如果没有 <auth-constraint>这表明任何身份的用户都可以访问相应的资源,如果加入了 <auth-constraint> 子元素,但是其内容为空,这表示所有身份的用户都被禁止访问相应的资源。对应SecurityConstraint.setAuthConstraint(true);
  • user-data-constraint:可选的元素指出在访问相关资源时使用任何传输层保护。它必须包含一个transport-guarantee子元素
  • NONE:对所用的通讯协议不加限制
  • CONFIDENTIAL:他们都只是简单地要求用SSL,一般是自动采用30x跳转。Api方式:SecurityConstraint.setUserConstraint("CONFIDENTIAL");
  • INTEGRAL:类似CONFIDENTIAL

3. 解决方案

3.1 直接Tomcat部署

这种方式一般是在应用springboot前的模式,包括:spring2-spring4时代。采用直接修改工程的Web.xml来解决。

在你工程的web.xml中配置:

  • 配置需要禁用的HTTP方法
<security-constraint>  
    <web-resource-collection>  
        <web-resource-name>acooly-default-policy</web-resource-name>
        <!-- 表示需要认证控制的URL -->
        <url-pattern>/*</url-pattern>  
        <!-- 以下多个是表示允许的http请求方法 -->
        <http-method>PUT</http-method>  
    	<http-method>DELETE</http-method>  
    	<http-method>HEAD</http-method>  
    	<http-method>OPTIONS</http-method>  
    	<http-method>TRACE</http-method>  
    </web-resource-collection>  
    <!-- 表示:需要认证 -->
    <auth-constraint/>  
</security-constraint>
  • 配置允许访问的HTTP方法
<security-constraint>  
    <web-resource-collection>  
        <web-resource-name>acooly-default-policy</web-resource-name>
        <!-- 表示需要认证控制的URL -->
        <url-pattern>/*</url-pattern>  
        <!-- 
            以下多个是表示允许的http请求方法 
            注意:实测区分大小写
        -->
        <http-method-omission>POST</http-method-omission>
        <http-method-omission>post</http-method-omission>
        <http-method-omission>GET</http-method-omission>
        <http-method-omission>get</http-method-omission>
    </web-resource-collection>  
    <!-- 表示:需要认证 -->
    <auth-constraint/>  
</security-constraint>

以上两种方式,推荐使用:“配置允许访问的HTTP方法”

3.2 springboot1.x

使用springboot的autoconfig特性,为tomcat增加扩展的自动配置功能。

@Configuration
@ConditionalOnWebApplication
@ConditionalOnClass(Tomcat.class)
public class TomcatAutoConfig {

    @Bean(name = "tomcatEmbeddedServletContainerFactory")
    public EmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory() {
        TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory() {
            @Override
            protected void postProcessContext(Context context) {
                SecurityConstraint securityConstraint = new SecurityConstraint();
                securityConstraint.setAuthConstraint(true);
                SecurityCollection collection = new SecurityCollection();
                collection.addPattern("/*");
                collection.addOmittedMethod("GET");
                collection.addOmittedMethod("get");
                collection.addOmittedMethod("post");
                collection.addOmittedMethod("POST");
                securityConstraint.addCollection(collection);
                context.addConstraint(securityConstraint);
            }
        };
        return tomcat;
    }
}

3.3 springboot2.x

原理同springboot1.x,只是在2.x版本后,可以直接采用TomcatServletWebServerFactory.addContextCustomizers发放增加ContextCustomizer扩展。

@Configuration
@ConditionalOnWebApplication
@ConditionalOnClass(Tomcat.class)
public class TomcatAutoConfig {
    @Bean
    public WebServerFactoryCustomizer<TomcatServletWebServerFactory> acoolyWebServerFactoryCustomizer() {
        return factory -> {
            // 禁用内置Tomcat的不安全请求方法
            factory.addContextCustomizers(context -> {
                SecurityConstraint securityConstraint = new SecurityConstraint();
                // 开启认证
                securityConstraint.setAuthConstraint(true);
                SecurityCollection collection = new SecurityCollection();
                // 对所有资源生效
                collection.addPattern("/*");
                // 以下是排除认证的非安全http方法(安全的方法)
                collection.addOmittedMethod("GET");
                collection.addOmittedMethod("get");
                collection.addOmittedMethod("POS");
                collection.addOmittedMethod("post");
                securityConstraint.addCollection(collection);
                context.addConstraint(securityConstraint);
            });
        };
    }
}