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

Struts2升级至6.1.1后Content-Security-Policy脚本加载报错

Struts2 6.1.1升级后Content Security Policy(CSP)违规问题解决

问题背景

将Struts2项目从struts2-core-2.5.30升级到struts2-core-6.1.1后,出现CSP安全策略违规错误,无法加载本地jQuery等脚本,错误提示如下:

[Report Only] Refused to load the script '' because it violates the following Content Security Policy directive: "script-src 'nonce-MOz6w31eaDHGUDfV__K8LEZ1' 'strict-dynamic' http: https:". Note that 'strict-dynamic' is present, so host-based allowlisting is disabled. Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback.

具体无法加载的脚本示例:

[Report Only] Refused to load the script <code>http://localhost:8080/Portal/html/js/jquery/jquery-1.8.3.min.js</code> because it violates the following Content Security Policy directive: "script-src 'nonce-MOz6w31eaDHGUDfV__K8LEZ1' 'strict-dynamic' http: https:". Note that 'strict-dynamic' is present, so host-based allowlisting is disabled. Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback.

[Report Only] Refused to load the script <code>http://localhost:8080/Portal/html/js/jquery/jquery-ui.1.10.4.min.js</code> because it violates the following Content Security Policy directive: "script-src 'nonce-MOz6w31eaDHGUDfV__K8LEZ1' 'strict-dynamic' http: https:". Note that 'strict-dynamic' is present, so host-based allowlisting is disabled. Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback.

已尝试的无效方案

  • 多种Meta标签配置:
<meta http-equiv="Content-Security-Policy" content="default-src 'self'">

<meta http-equiv="Content-Security-Policy" content="default-src *;
    style-src * 'unsafe-inline'; script-src * 'unsafe-inline'
    'unsafe-eval'; img-src * data: 'unsafe-inline'; connect-src *
    'unsafe-inline'; frame-src *;">

<meta http-equiv="Content-Security-Policy" content="default-src  'nonce-rAnd0m'">
<script src="${pageContext.request.contextPath}/html/js/jquery/jquery-1.8.3.min.js" type="text/javascript" nonce="rAnd0m123"></script> 
  • 自定义Interceptor添加响应头:
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.StrutsStatics;

public class SessionInterceptor extends AbstractInterceptor{

   private static final long serialVersionUID = 1L;

   public String intercept(ActionInvocation invocation) throws Exception {
     
    ActionContext ac = invocation.getInvocationContext();
    HttpServletResponse response = (HttpServletResponse) ac.get(StrutsStatics.HTTP_RESPONSE);

    response.addHeader("X-Frame-Options", "SAMEORIGIN");
    response.addHeader("Content-Security-Policy-Report-Only", "default-src 'self'; script-src 'self' 'unsafe-inline'; object-src 'none'; style-src 'self' 'unsafe-inline'; img-src 'self'; media-src 'none'; frame-src 'none'; font-src 'self'; connect-src 'self'; report-uri REDACTED");
    response.addHeader("X-Content-Security-Policy-Report-Only", "default-src 'self'; script-src 'self' 'unsafe-inline'; object-src 'none'; style-src 'self' 'unsafe-inline'; img-src 'self'; media-src 'none'; frame-src 'none'; font-src 'self'; connect-src 'self'; report-uri REDACTED");
    return invocation.invoke();
}

}
  • 升级jQuery版本(从1.8.3升级)

解决方案

核心原因

Struts2 6.x版本默认启用了内置的CSP拦截器,它会自动添加带有nonce和strict-dynamic的CSP头,手动添加的Meta标签或自定义拦截器的头会被覆盖或冲突——浏览器会合并所有CSP规则并取最严格限制。

具体解决步骤

  1. 禁用内置CSP拦截器(按需选择)
    如果不需要默认CSP防护,直接在struts.xml中关闭内置拦截器:
<struts>
    <constant name="struts.security.csp.enabled" value="false" />
</struts>
  1. 通过Struts配置自定义CSP规则(推荐)
    若需保留CSP防护,不要手动添加头,而是通过Struts配置修改规则:
<struts>
    <!-- 启用CSP(默认值为true) -->
    <constant name="struts.security.csp.enabled" value="true" />
    <!-- 设置模式:REPORT_ONLY仅上报不拦截,ENFORCING直接拦截 -->
    <constant name="struts.security.csp.mode" value="REPORT_ONLY" />
    <!-- 自定义script-src规则,Struts会自动生成并注入nonce值 -->
    <constant name="struts.security.csp.policy.script-src" value="'self' 'unsafe-inline' 'nonce-${nonce}' http: https:" />
    <!-- 按需配置其他规则 -->
    <constant name="struts.security.csp.policy.default-src" value="'self'" />
    <constant name="struts.security.csp.policy.style-src" value="'self' 'unsafe-inline'" />
</struts>
  1. 使用Struts自动生成的nonce值
    若依赖nonce信任脚本,需在JSP中引用Struts注入的${nonce}变量,而非手动写死:
<script src="${pageContext.request.contextPath}/html/js/jquery/jquery-1.8.3.min.js" type="text/javascript" nonce="${nonce}"></script>
  1. 清理无效配置
    移除所有手动添加的CSP Meta标签,以及自定义拦截器中的CSP响应头,避免规则冲突。

关键说明

  • strict-dynamic仅信任由已信任脚本动态加载的资源,直接通过标签加载的脚本需显式加入script-src白名单,或用nonce/hash标记信任。
  • Struts2 6.x内置CSP拦截器优先级高于自定义响应头和Meta标签,必须通过Struts配置修改规则。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 05:30:53