必须调用 iris.Default() 才能自动注入 X-Content-Type-Options、X-XSS-Protection、X-Frame-Options 等基础安全头;若用 iris.New(),需手动添加 iris.Secure 中间件,且 CSP 需自行通过 ctx.Header() 设置,注意 frame-ancestors 与 X-Frame-Options 互斥,HSTS 仅 HTTPS 有效。

如何用 iris.Default() 启用基础安全头
默认的 iris.New() 不带任何安全头,必须显式调用 iris.Default() 才能自动注入 X-Content-Type-Options、X-XSS-Protection(已逐步弃用但 Iris 仍保留)、X-Frame-Options 等基础防护头。这不是可选项——不调用它,这些头根本不会出现。
常见错误是直接写 app := iris.New() 然后以为中间件会补全,结果响应里压根没有 X-Frame-Options: DENY,导致页面被嵌入恶意站点。
-
iris.Default()内部已注册iris.Recover、iris.Logger和iris.Secure中间件,其中iris.Secure负责写安全头 - 若你手动用了
iris.New(),就得自己加:app.Use(iris.Secure) -
iris.Secure不处理 CSP,它只管传统浏览器兼容性头;CSP 需单独配置
自定义 Content-Security-Policy 头的正确写法
CSP 是现代 Web 安全的核心,但 Iris 没有内置 DSL,必须用 ctx.Header() 在中间件或全局 handler 里硬写。错写成 ctx.ResponseWriter().Header().Set() 会导致部分请求漏设(比如重定向时 header 被覆盖)。
典型场景:前端资源全走 CDN,JS 只允许自己域名和 trusted-cdn.com,禁止内联脚本:
app.Use(func(ctx iris.Context) {
ctx.Header("Content-Security-Policy", "default-src 'self'; script-src 'self' https://trusted-cdn.com; object-src 'none'; base-uri 'self'; frame-ancestors 'none'")
ctx.Next()
})
- 必须放在所有
ctx.Next()之前,否则后续 handler 可能提前写响应体,header 就失效 - 不要在 controller 方法里重复设——容易和中间件冲突,统一收口到中间件
- 开发环境建议先用
Content-Security-Policy-Report-Only收集违规日志,再切正式策略
为什么 X-Frame-Options 和 CSP 的 frame-ancestors 不能共存
当两者同时存在时,Chrome 和 Firefox 会优先遵守 frame-ancestors,直接忽略 X-Frame-Options。Iris 的 iris.Secure 默认写的是 X-Frame-Options: SAMEORIGIN,如果你又手动加了 frame-ancestors 'none',前者就形同虚设。
- 线上服务应彻底禁用
X-Frame-Options:在iris.Secure后再加一个中间件,用ctx.ResponseWriter().Header().Del("X-Frame-Options") -
frame-ancestors 'none'比SAMEORIGIN更严格,且支持多源、支持 iframe 嵌套控制,是唯一推荐方案 - 注意 Safari 旧版本(≤15.4)不支持
frame-ancestors,若需兼容,得降级回X-Frame-Options并放弃frame-ancestors
Strict-Transport-Security 头必须 HTTPS 下才生效
Strict-Transport-Security(HSTS)头在 HTTP 请求中会被浏览器直接丢弃,Iris 不会阻止你设,但毫无意义。生产环境若没配 TLS,加这行等于没加。
- 正确做法:只在 HTTPS 入口处设,例如 Nginx 或 Cloudflare 终止 SSL 后,再透传给 Iris;或 Iris 自己跑 HTTPS 时,在中间件里判断
ctx.Request().TLS != nil再写头 - 开发时 localhost 无法测试 HSTS,浏览器会静默忽略,别浪费时间调试
- 首次设置建议用短 max-age(如
max-age=300),确认无误后再升到max-age=31536000
frame-ancestors 和 X-Frame-Options 的互斥关系——很多人图省事两个都写,结果以为防住了点击劫持,其实浏览器只认一个。


















