You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Nginx同时作为HTTP服务器与反向代理时如何过滤非前端来源请求

问题核心说明

首先明确几个方案的天然缺陷,不要在这上面浪费时间:

  • 直接在Nginx加固定自定义请求头做校验完全没用:任何调用方都可以手动在请求里加相同的头,防君子不防小人。
  • allow/deny IP规则不适用:所有请求(不管是前端页面触发还是用户直接调用接口)的源IP都是客户端公网IP,和你看到的X-Real-IP一致,根本没有IP维度的区分特征。
  • 基于Referer头校验误杀率高、易伪造:一方面隐私插件、浏览器安全配置可能主动剥离Referer头,导致正常用户被拦截;另一方面Referer可以被任意客户端伪造,没有安全价值。

另外要明确:不存在技术手段能100%区分「用户浏览器中页面代码发起的请求」和「用户在控制台手动构造/本地脚本发起的请求」——前端能拿到的所有凭证,用户在自己的浏览器里都能拿到,你能做到的是拦截跨站恶意调用、外部设备/非浏览器脚本直连刷接口的场景,最终的安全底线必须是后端的身份校验。


高性价比落地方案(Nginx层拦截,改动量极小)

采用双提交Cookie模式的CSRF校验逻辑,Nginx层即可完成大部分校验,前端只需要加几行请求拦截逻辑,不需要改动后端代码。

实现原理

  1. 用户首次访问前端页面时,Nginx自动种下一个随机值的Cookie,同域下前端可以读取这个Cookie值,第三方站点/外部脚本无法跨域读取该Cookie内容。
  2. 前端发起/api路径请求时,自动从Cookie中读取该随机值,放到自定义请求头X-CSRF-Token中携带。
  3. Nginx处理/api请求时,校验请求头中的X-CSRF-Token值是否和Cookie中的随机值一致,一致才转发给后端,不一致直接返回403。

这个方案可以拦住所有跨站恶意请求、外部脚本直连接口的场景——外部调用方根本拿不到Cookie里的随机值,就无法构造出合法的请求头。

配置示例

1. Nginx配置

http {
    # 可选:加API频率限制,进一步防刷
    limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;

    server {
        listen 443 ssl;
        server_name your.domain.com;
        # 省略SSL证书相关配置

        # 前端静态资源路径
        location / {
            root /your/frontend/dist/directory;
            index index.html;
            # 首次访问没有CSRF Cookie时,种下随机token
            if ($cookie__csrf_token = "") {
                add_header Set-Cookie "_csrf_token=$request_id; Path=/; SameSite=Strict; Secure; HttpOnly=false" always;
            }
            try_files $uri $uri/ /index.html;
        }

        # /api反向代理路径
        location /api {
            # CSRF校验:头和Cookie中的token必须匹配
            if ($http_x_csrf_token != $cookie__csrf_token) {
                return 403;
            }
            # 应用频率限制
            limit_req zone=api_limit burst=20 nodelay;
            # 反向代理转发到本地Node服务
            proxy_pass http://localhost:your_node_service_port;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
}

2. 前端改动

只需要给你的请求库加一个全局拦截器,每次发请求前从Cookie中读取_csrf_token的值,塞到请求头里即可,以axios为例:

import axios from 'axios'

// 从Cookie读CSRF Token的工具方法
function getCsrfToken() {
  return document.cookie
    .split('; ')
    .find(row => row.startsWith('_csrf_token='))
    ?.split('=')[1]
}

axios.interceptors.request.use(config => {
  if (config.url.startsWith('/api')) {
    config.headers['X-CSRF-Token'] = getCsrfToken()
  }
  return config
})

必须补的安全底线

Nginx层的拦截只能减少非法请求,不能替代后端的身份校验逻辑。你当前后端默认接收所有请求、完全信任前端传参的逻辑有本质安全风险:

  • 所有前端侧的认证逻辑、参数都可以被用户篡改,前端永远不能作为信任边界。
  • 你提到的第三方认证ID,后端收到之后必须调用第三方接口校验ID的合法性、对应用户身份、权限,校验通过才处理请求,不要直接信任前端传过来的ID值。

内容的提问来源于stack exchange,提问作者shaolintl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 11:01:24