HTTP请求方法限制只允许GET和POST,本质上就是在Web服务器层面做一道"安检门"——把PUT、DELETE、OPTIONS、PATCH、TRACE等非核心方法全部拦截掉,只放行最常用的两种。这样做的核心目的是缩小攻击面,防止攻击者利用非常规HTTP方法绕过安全策略、执行未授权操作或者触发服务器漏洞。具体怎么做?在Nginx里加一段if判断拒绝非GET/POST请求,在Apache里用Rewrite规则拦截,在IIS里通过请求筛选模块配置,在代码层面也可以用中间件统一过滤。下面我把每种方案的原理、配置细节、注意事项全部讲透。

为什么要限制HTTP请求方法?先搞清楚风险在哪

HTTP协议定义了多种请求方法,GET用于获取资源,POST用于提交数据,这两个是Web应用最基础的交互方式。但除此之外还有PUT(上传/替换资源)、DELETE(删除资源)、PATCH(部分更新)、OPTIONS(查询支持的方法)、TRACE(回显请求)等等。这些方法本身不是"坏"的,RESTful API设计中会大量使用PUT和DELETE。但问题在于,很多传统网站、CMS系统、后台管理系统根本不需要这些方法,开放它们就等于多开了几扇没人看守的窗户。

攻击者利用非常规方法能干什么?举几个真实场景:用PUT方法直接上传一个WebShell文件到服务器目录;用DELETE方法删除关键配置文件或用户数据;用TRACE方法发起跨站追踪攻击(XST);用OPTIONS方法探测服务器支持哪些接口和方法,为后续攻击做侦察。2010年Apache的"Range头攻击"就是利用了非常规请求的处理缺陷。所以,限制方法是一种"默认拒绝"的安全策略,属于纵深防御体系里非常实用的一环。

Nginx中限制HTTP请求方法的完整配置

Nginx是目前使用量最大的Web服务器和反向代理,它提供了$request_method变量可以直接判断当前请求使用的方法。最简单的做法是在server块或者location块里加if判断:

if ($request_method !~ ^(GET|POST)$ ) {
    return 405;
}

这段代码的意思是:如果请求方法不是GET也不是POST,直接返回405 Method Not Allowed状态码。405是HTTP标准状态码,比直接返回403更语义化,告诉客户端"这个方法不被允许"。如果你想更彻底,可以针对特定路径做限制,比如只对上传接口、API接口做方法过滤,而不是全局拦截:

location /api/ {
    if ($request_method !~ ^(GET|POST)$ ) {
        return 405;
    }
    proxy_pass http://backend;
}

需要注意一个坑:Nginx的if指令在某些场景下有"if is evil"的说法,但在这里只是简单的返回操作,不涉及复杂逻辑,实际使用是安全的。另外,如果你的网站需要支持WebDAV或者某些特殊功能用到了PUT/DELETE,那就不能全局限制,要按路径精细化配置。

Apache中通过Rewrite规则实现方法限制

Apache的配置逻辑和Nginx不同,它主要通过mod_rewrite模块来实现。在.htaccess文件或者虚拟主机配置里可以这样写:

RewriteEngine On
RewriteCond %{REQUEST_METHOD} !^(GET|POST)$ [NC]
RewriteRule .* - [R=405,L]

这段规则的逻辑是:当请求方法不匹配GET或POST时,重写到当前URL并返回405状态码。[NC]表示不区分大小写,[L]表示这是最后一条规则。如果你用的是Apache 2.4以上版本,还可以用更现代的方式,在Directory或Location段里用Require指令配合表达式:

<RequireAll>
    Require method GET POST
</RequireAll>

这种写法更清晰,而且Apache会自动处理不允许的方法并返回405。对于WordPress、Drupal这类CMS系统,通常在根目录的.htaccess里加一条Rewrite规则就够了,不会影响后台正常的文件上传(因为上传走的是POST)。

IIS服务器上的请求筛选配置方法

Windows Server上跑IIS的站长,可以通过"请求筛选"(Request Filtering)功能来限制方法。操作路径是:打开IIS管理器 → 选择网站 → 双击"请求筛选" → 切换到"HTTP谓词"选项卡 → 在"允许的谓词"里只保留GET和POST,把其他的删掉。这样IIS会自动拒绝任何非GET/POST的请求并返回405.3错误。

如果你想用web.config文件来管理(方便版本控制和部署),可以这样配置:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.webServer>
    <security>
      <requestFiltering>
        <verbs applyToWebDAV="false">
          <add verb="GET" allowed="true" />
          <add verb="POST" allowed="true" />
          <add verb="HEAD" allowed="false" />
          <add verb="PUT" allowed="false" />
          <add verb="DELETE" allowed="false" />
        </verbs>
      </requestFiltering>
    </security>
  </system.webServer>
</configuration>

注意这里HEAD方法默认也被禁了。HEAD和GET几乎一样只是不返回响应体,很多场景下是需要的(比如CDN缓存验证、链接检查)。如果你的业务需要HEAD,就把allowed改成true。这个配置文件可以直接放在网站根目录,IIS会自动加载。

应用层代码实现:中间件过滤请求方法

除了在Web服务器层面拦截,在应用代码层面做一层过滤是更灵活的方案。以Node.js的Express框架为例,可以写一个全局中间件:

app.use((req, res, next) => {
    const allowedMethods = ['GET', 'POST'];
    if (!allowedMethods.includes(req.method)) {
        return res.status(405).json({
            error: 'Method Not Allowed',
            message: 'Only GET and POST methods are permitted'
        });
    }
    next();
});

Python的Flask框架可以用装饰器或者before_request钩子:

@app.before_request
def limit_methods():
    if request.method not in ['GET', 'POST']:
        return 'Method Not Allowed', 405

Java的Spring Boot可以通过Filter或者HandlerInterceptor实现:

@Component
public class MethodFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, 
                         FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        String method = httpRequest.getMethod();
        if (!"GET".equals(method) && !"POST".equals(method)) {
            HttpServletResponse httpResponse = (HttpServletResponse) response;
            httpResponse.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
            return;
        }
        chain.doFilter(request, response);
    }
}

应用层过滤的好处是可以做更细粒度的控制,比如对某些接口允许PUT,对某些只允许GET。但缺点是请求已经到达应用了,如果前面没有Web服务器层面的拦截,恶意请求仍然会消耗应用资源。所以最佳实践是"服务器层+应用层"双重过滤。

限制方法之后需要注意的几个关键问题

第一,不要一刀切。如果你的网站有RESTful API、文件管理功能、WebDAV支持,这些场景天然需要PUT、DELETE等方法。全局限制会导致这些功能直接瘫痪。正确做法是按路径或按模块分别配置,只对不需要非常规方法的区域做限制。

第二,405状态码要正确返回。有些人图省事直接返回403 Forbidden,这在语义上是错误的。403表示"你没有权限",405表示"这个方法不被允许"。对于安全审计和日志分析来说,正确的状态码能帮助你快速定位问题。同时建议在返回405时附带Allow响应头,告诉客户端哪些方法是被允许的:

add_header Allow "GET, POST" always;

第三,测试要充分。配置完之后用curl命令验证一下:

curl -X PUT http://yourdomain.com/test
curl -X DELETE http://yourdomain.com/test
curl -X OPTIONS http://yourdomain.com/test

如果返回405就说明配置生效了。同时也要确认正常的GET和POST请求不受影响。

第四,这只是安全策略的一层,不能替代其他防护。限制HTTP方法防的是"利用非常规方法攻击"这一类威胁,但SQL注入、XSS、CSRF、文件上传漏洞这些问题,光靠限制方法是解决不了的。它应该和WAF(Web应用防火墙)、输入验证、权限控制、HTTPS加密等措施配合使用,形成完整的安全体系。

从合规和安全标准角度看方法限制的意义

在等保2.0、ISO 27001、PCI DSS等安全合规框架中,都有"最小权限原则"和"减少攻击面"的要求。限制不必要的HTTP请求方法就是这两个原则的具体落地。很多安全扫描工具(如Nessus、OpenVAS)在做Web安全检测时,会专门检查服务器是否开放了不必要的HTTP方法,如果发现PUT、DELETE、TRACE等方法可用且没有合理用途,会标记为中高风险项。所以做好这一步,不仅是主动防御,也是过安全审计的基本要求。

还有一个容易被忽视的点:TRACE方法。虽然现代浏览器已经很少主动发送TRACE请求,但如果服务器支持TRACE,攻击者可以利用它发起XST(Cross-Site Tracing)攻击,窃取用户的Cookie信息。所以在限制方法的时候,TRACE一定要关掉。在Apache里可以用TraceEnable Off,在Nginx里没有内置TRACE支持(默认就不响应),IIS里需要在请求筛选中明确禁用。

总结:怎么做才是最优解

网站安全之HTTP请求方法限制,核心思路就是"默认拒绝、按需放行"。具体操作上,先梳理你的网站哪些功能需要哪些HTTP方法,然后在Web服务器层面做全局或局部限制,再在应用层加一道保险。配置不复杂,十分钟就能搞定,但效果实实在在——它砍掉了一整类攻击路径,让攻击者少了很多可利用的入口。不要觉得这是小题大做,安全这件事从来都是细节决定成败。把每一个不起眼的小口子堵上,整体安全性就会上一个台阶。