Play 2.7中CSP过滤器的正确使用方法及问题咨询
看起来你在Play 2.7配置CSP nonce的时候踩了几个常见的坑,我帮你一步步排查解决:
1. 修正配置的前缀问题
Play框架的CSP配置项是嵌套在play.filters命名空间下的,你当前直接写csp { ... }的配置根本不会被Play识别加载。正确的配置结构应该是:
play.filters.csp { nonce { enabled = true pattern = "%CSP_NONCE_PATTERN%" header = false # 这个配置控制是否发送单独的`Nonce`头,而非Content-Security-Policy头中的nonce,通常保持false即可 } directives { base-uri = "'none'" object-src = "'none'" script-src = ${play.filters.csp.nonce.pattern} "'unsafe-inline' 'unsafe-eval' 'strict-dynamic' https: http:" } }
之前的配置因为缺少play.filters前缀,导致CSP策略完全没生效,这也是内联JS不受限制、nonce不生成的核心原因。
2. 确保CSP过滤器已启用
Play 2.7需要手动将CSPSecurityFilter加入到过滤器链中。如果你的项目使用默认的Filters类,需要在app/Filters.scala中添加该过滤器:
import play.api.http.DefaultHttpFilters import play.filters.csp.CSPSecurityFilter class Filters( cspFilter: CSPSecurityFilter ) extends DefaultHttpFilters(cspFilter)
如果没有这个类,或者未添加CSPSecurityFilter,CSP规则不会被应用到任何请求上。
3. 修正模板中的Nonce引用
在Twirl模板中使用CSPNonce.attr之前,必须先导入对应的类:
@import play.filters.csp.CSPNonce
之后再在script标签中使用:
<script @{CSPNonce.attr} src="/path/to/your/script.js"></script>
这样生成的HTML才会自动带上nonce="随机值"的属性。
4. 验证CSP头的生成
开启正确配置后,你需要查看响应头中的Content-Security-Policy字段,而非单独的Nonce头。正常情况下,这个头会包含类似script-src 'nonce-abc123xxx' 'unsafe-inline' ...的内容,其中abc123xxx就是自动生成的nonce值。
5. 关于内联JS的问题
你现在所有内联JS都能加载,本质是因为CSP策略完全没生效。当配置正确后,只有带有正确nonce属性的脚本(或符合strict-dynamic规则的脚本)才能被浏览器允许,未标记的内联JS会被直接阻止。
内容的提问来源于stack exchange,提问作者user3248346

