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

Nginx+code-server反向代理下非浏览器POST请求返回401排查

Stripe Webhook接口返回401错误排查方案

问题背景

2023年4月28日编辑:补充Nginx相关信息

在React/Node项目中集成Stripe支付时,服务器需处理两类POST请求:

  • /create-payment-intent:来自浏览器的请求,运行正常
  • /webhook:来自Stripe服务器的请求,返回HTTP 401错误,请求未到达Express处理器

环境架构

请求需经过两层反向代理:

  • Nginx将https://<my-code-server-domain>的请求转发至localhost:8082的code-server
  • code-server将https://<my-code-server-domain>/proxy/3024/*的请求转发至localhost:3024的Node应用

请求示例:

  • https://<my-code-server-domain>/proxy/3024/create-payment-intent
  • https://<my-code-server-domain>/proxy/3024/webhook

服务器代码片段

const app = express()
app.post("/webhook",  express.raw({type: 'application/json'}), async (req, res) => {
    let event = req.body;
    ...

排查现状

  • 断点显示webhook请求未进入Express处理器,说明在到达处理器前被拦截
  • 已尝试添加cors模块及手动设置宽松CORS头部,无效
  • 使用Stripe官方转发工具测试,结果一致
  • Nginx access.log显示:/proxy/3024/create-payment-intent返回200,/proxy/3024/webhook返回401
  • Nginx debug日志显示401是从上游(code-server)返回的

排查方向与解决方案

1. 解除code-server代理的身份验证拦截

code-server的/proxy/*路径默认会启用身份验证拦截,浏览器请求携带了code-server的会话Cookie所以能通过,但Stripe的webhook请求无此Cookie,因此被拦截返回401。

解决方法:

  • 修改code-server的config.yaml配置,将webhook路径加入免认证白名单:
    auth:
      bypass:
        - "/proxy/3024/webhook"
    
  • 重启code-server生效

2. 检查Node应用的中间件拦截

确认Node应用中是否存在全局身份验证中间件,误拦截了webhook请求。需确保/webhook路径跳过所有无关的认证中间件,仅保留必要的express.raw解析中间件。

3. 验证Nginx代理配置

确保Nginx正确传递请求头(尤其是Stripe-Signature),且不修改原始请求体(Stripe签名验证依赖原始请求内容)。示例配置片段:

location / {
    proxy_pass http://localhost:8082;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_request_buffering off; # 禁用请求缓冲,避免修改请求体
}

4. 直接测试Node应用接口

在服务器本地用curl直接请求Node应用的webhook接口,确认接口本身是否正常:

curl -X POST http://localhost:3024/webhook \
  -H "Content-Type: application/json" \
  -d '{"type": "payment_intent.succeeded"}'

如果返回200,说明问题确实出在代理层;如果仍返回401,排查Node应用内部的拦截逻辑。

5. 后续补充Stripe签名验证

当请求能到达Express处理器后,需添加Stripe官方签名验证逻辑,避免伪造请求:

const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
app.post('/webhook', express.raw({type: 'application/json'}), async (req, res) => {
  const sig = req.headers['stripe-signature'];
  let event;
  try {
    event = stripe.webhooks.constructEvent(
      req.body,
      sig,
      process.env.STRIPE_WEBHOOK_SECRET
    );
  } catch (err) {
    return res.status(400).send(`Webhook Error: ${err.message}`);
  }
  // 处理对应事件逻辑
  res.json({received: true});
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 15:12:00