Sec-Fetch-*是浏览器自动添加的Forbidden header,无法通过HTML、meta标签或JS手动设置;其值由请求发起方式(如导航、img标签、fetch)自动决定,用于服务端辅助安全校验。

浏览器自动加 Sec-Fetch-* 请求头,你无法在 HTML 中“制作”或手动设置它们——所有尝试用 <meta>、fetch() 配置项、或 JS 拦截修改的行为都会失败,因为这些是 Forbidden header。
为什么 Sec-Fetch-Dest 和 Sec-Fetch-Mode 在 HTML 里不出现?
这两个字段由浏览器根据请求发起方式自动注入,不是开发者可控的 HTTP 头:
-
Sec-Fetch-Dest: document只在页面导航(如点击链接、location.href跳转)时出现;<img src>触发的是Sec-Fetch-Dest: image;<script src>是script;fetch()默认是empty(除非显式指定destination) -
Sec-Fetch-Mode完全取决于 fetch/fetch API 的mode选项:fetch(url, { mode: 'cors' })→Sec-Fetch-Mode: cors;{ mode: 'navigate' }仅限浏览器内部导航,JS 不可触发 -
<meta http-equiv>或XMLHttpRequest.setRequestHeader()对Sec-Fetch-*无效,会静默忽略
fetch() 中能影响 Sec-Fetch-Dest 的唯一参数
只有 destination 选项能间接改变 Sec-Fetch-Dest 值,但它受限于实际资源用途,不能乱设:
-
fetch('/api/data', { destination: 'document' })→ 浏览器拒绝,报错TypeError: Failed to execute 'fetch' on 'Window': Invalid destination - 合法组合极少:比如
{ destination: 'image' }仅当 URL 确实返回图片且你准备用createImageBitmap()处理时才合理 - 最常用且安全的写法是不设
destination(默认empty),让浏览器按上下文推断
服务端依赖 Sec-Fetch-* 做防护时的真实限制
别把它们当银弹——兼容性和可靠性远不如传统手段:
立即学习“前端免费学习笔记(深入)”;
- iOS Safari(尤其旧版本)可能完全不发
Sec-Fetch-Mode,导致你的 CSRF 防护逻辑漏判;Sec-Fetch-Site: cross-site在 iframe 内嵌场景下也可能缺失 - 本地缓存命中时(
304或memory cache),整个请求不走网络,Sec-Fetch-*全部消失 - 服务端若只校验
Sec-Fetch-Mode: cors就放行 API 请求,而忽略Origin和Credentials状态,反而会引入新漏洞 - 真正该做的:用
Sec-Fetch-Site+Sec-Fetch-Mode做辅助判断,主逻辑仍靠SameSite=StrictCookie + CSRF Token
想靠 HTML 标签或前端代码“生成”合规的 Sec-Fetch-Dest,本质是误解了它的设计意图——它不是配置项,而是浏览器对“你正在做什么”的诚实报告。真正要动手的地方,在服务端解析逻辑和 fallback 策略上,而不是前端伪造。


















