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

在Node.js(Express+EJS)集成Stripe时解决CSP报错问题

Stripe集成Express+EJS时的CSP问题排查与解决

报错原因

你看到的Refused to execute inline script报错,核心是当前配置的Content Security Policy(CSP)规则script-src 'self'限制过严:

  1. 该规则仅允许加载同源(自身服务器)的脚本,同时禁止所有内联执行的脚本代码;
  2. Stripe的SDK从https://js.stripe.com加载,属于外部域名,不在'self'范围内;而且Stripe SDK初始化时会动态生成内联脚本,这也会被CSP拦截;
  3. 你怀疑的EJS传入公钥的方式(用data-public-key属性存储)本身不是内联脚本,不会触发这个报错,之前的猜测不对。

解决方法

1. 调整CSP规则(核心解决步骤)

如果你的Express项目用了helmet这类安全中间件,默认会启用严格的CSP,需要手动配置允许Stripe相关资源,推荐用Nonce方式(安全性更高),测试环境也可以临时放宽规则。

方式一:使用Nonce(生产环境推荐)

Nonce是每次请求生成的随机字符串,只有带有这个字符串的脚本会被CSP允许执行:

  • 服务器端修改路由代码,生成Nonce并设置CSP头:
    const crypto = require('crypto');
    stripeRoute.get("/checkout", isAuth, (req, res) => {
      // 生成随机nonce
      const nonce = crypto.randomBytes(16).toString('hex');
      const publicKey = String(process.env.STRIPE_PUBLIC_KEY);
      
      // 设置CSP响应头
      res.setHeader(
        'Content-Security-Policy',
        `script-src 'self' 'nonce-${nonce}' https://js.stripe.com; style-src 'self' https://js.stripe.com; frame-src https://js.stripe.com;`
      );
      
      return res.render("checkout", { publicKey, nonce });
    });
    
  • 修改EJS模板,给所有外部脚本标签加上nonce属性:
    <script nonce="<%= nonce %>" src="https://js.stripe.com/v3/"></script>
    <script nonce="<%= nonce %>" src="/js/client.js"></script>
    

方式二:临时放宽规则(仅测试环境用)

如果是测试阶段,不想折腾Nonce,可以直接允许Stripe域名和内联脚本(生产环境禁止使用,存在安全风险):

stripeRoute.get("/checkout", isAuth, (req, res) => {
  const publicKey = String(process.env.STRIPE_PUBLIC_KEY);
  
  res.setHeader(
    'Content-Security-Policy',
    `script-src 'self' 'unsafe-inline' https://js.stripe.com; style-src 'self' https://js.stripe.com; frame-src https://js.stripe.com;`
  );
  
  return res.render("checkout", { publicKey });
});

2. 优化公钥传递方式(可选)

你当前用data属性存公钥的方式没问题,也可以用更简洁的全局变量方式(需要配合CSP规则):

  • EJS模板里添加带Nonce的内联脚本,定义全局变量:
    <script nonce="<%= nonce %>">
      window.stripePublicKey = "<%= publicKey %>";
    </script>
    
  • 修改client.js直接使用全局变量:
    document.addEventListener("DOMContentLoaded", () => {
      const stripe = Stripe(window.stripePublicKey);
      // 后续代码不变...
    });
    

3. 检查其他内联脚本

确认页面中没有其他直接写在<script>标签里的执行代码,如果有,要么移到外部JS文件,要么给对应的脚本标签加上Nonce。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 14:44:53