前端请求加了 Nonce 为啥还是被拦截?

司空广利 阅读 14

我在做 CSP 安全策略,给每个 fetch 请求加了 Nonce,但浏览器还是报“Refused to execute inline script”错误,根本没走到请求那步。是不是我理解错了 Nonce 的用法?

我试过在 meta 标签里加 nonce,也在请求头里带了,但好像都不对。下面是我现在发请求的代码:

const nonce = 'a1b2c3d4'; // 从后端拿到的真实 nonce
fetch('/api/data', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-Nonce': nonce
  },
  body: JSON.stringify({ action: 'load' })
});

这写法有问题吗?Nonce 不是应该这样传的?

我来解答 赞 3 收藏
二维码
手机扫码查看
2 条解答
Top丶广红
哎兄弟,这个坑我去年踩过,当时debug到半夜。关键点你搞混了,Nonce根本不是用来传请求头的,是给内联脚本用的。

CSP的Nonce是这么用的:
1. 首先服务器生成一个随机Nonce(比如'a1b2c3d4')
2. 把这个Nonce放到CSP头里:script-src 'nonce-a1b2c3d4'
3. 然后在页面的

血泪教训啊!我当时也以为Nonce是给API请求用的,结果完全跑偏了。你遇到的"Refused to execute inline script"就是因为内联脚本没加nonce属性,跟fetch请求半毛钱关系都没有。

如果非要保护API请求,应该用CSRF Token而不是Nonce。Nonce是专门解决CSP内联脚本执行问题的,两个完全是不同的安全机制。

顺便说下,现在很多项目都用webpack打包了,压根不需要内联脚本,直接用hash白名单更安全:
script-src 'sha256-xxxx
点赞 2
2026-03-08 10:13
萌新.振巧
问题在于你把 Nonce 用错了地方——Nonce 是给浏览器识别 内联脚本(inline script) 是否合法用的,不是用来给 fetch 请求传参数的。
你发的这个 fetch 请求是网络请求,不是内联脚本,浏览器根本不看这个头;
真正该做的是:后端在 CSP 头里写 script-src 'nonce-a1b2c3d4',前端页面里内联的 才会被放行。

你要是想动态执行 JS,别用 fetch 传 nonce,改用 fetch('/api/data') 拿到数据后,用 eval('('+data+')') 或创建
点赞 5
2026-02-24 20:10