如何为Struts CSP拦截器全局设置base-uri?
解决Struts 6全局配置CSP base-uri的方案
Struts 6默认的CSP拦截器仅通过CSPSettings注解支持Action级别的有限配置(仅切换报告/强制模式、修改报告地址),要全局设置base-uri可以通过以下几种方式实现:
方式一:自定义CSP拦截器继承默认实现
继承默认的ContentSecurityPolicyInterceptor,重写buildCspDirectives方法注入全局base-uri配置:
public class CustomCSPInterceptor extends ContentSecurityPolicyInterceptor { @Override protected Map<String, String> buildCspDirectives(ActionInvocation invocation) { Map<String, String> directives = super.buildCspDirectives(invocation); // 替换为你的站点标准base-uri值 directives.put("base-uri", "'self' https://your-domain.com"); return directives; } }
然后在struts.xml中替换默认的CSP拦截器,重新定义默认栈:
<struts> <package name="default" extends="struts-default"> <interceptors> <interceptor name="customCsp" class="com.yourpackage.CustomCSPInterceptor"/> <interceptor-stack name="defaultStack"> <!-- 用自定义CSP拦截器替换默认的csp拦截器 --> <interceptor-ref name="customCsp"/> <!-- 以下为默认栈原有拦截器,保持不变 --> <interceptor-ref name="exception"/> <interceptor-ref name="alias"/> <interceptor-ref name="servletConfig"/> <interceptor-ref name="prepare"/> <interceptor-ref name="i18n"/> <interceptor-ref name="chain"/> <interceptor-ref name="scopedModelDriven"/> <interceptor-ref name="modelDriven"/> <interceptor-ref name="fileUpload"/> <interceptor-ref name="checkbox"/> <interceptor-ref name="datetime"/> <interceptor-ref name="multiselect"/> <interceptor-ref name="staticParams"/> <interceptor-ref name="actionMappingParams"/> <interceptor-ref name="params"/> <interceptor-ref name="conversionError"/> <interceptor-ref name="validation"> <param name="excludeMethods">input,back,cancel,browse</param> </interceptor-ref> <interceptor-ref name="workflow"> <param name="excludeMethods">input,back,cancel,browse</param> </interceptor-ref> <interceptor-ref name="debugging"/> </interceptor-stack> </interceptors> <default-interceptor-ref name="defaultStack"/> </package> </struts>
方式二:自定义可配置参数的CSP拦截器
给自定义拦截器添加可配置参数,方便在struts.xml中直接修改base-uri:
public class ConfigurableCSPInterceptor extends ContentSecurityPolicyInterceptor { private String baseUri; public void setBaseUri(String baseUri) { this.baseUri = baseUri; } @Override protected Map<String, String> buildCspDirectives(ActionInvocation invocation) { Map<String, String> directives = super.buildCspDirectives(invocation); if (baseUri != null && !baseUri.isEmpty()) { directives.put("base-uri", baseUri); } return directives; } }
在struts.xml中配置参数:
<interceptors> <interceptor name="customCsp" class="com.yourpackage.ConfigurableCSPInterceptor"> <param name="baseUri">'self' https://your-domain.com</param> </interceptor> <!-- 重新定义默认栈同上 --> </interceptors>
方式三:支持全局配置文件的CSP拦截器
如果需要更灵活的配置管理,可以读取外部配置文件中的base-uri:
- 创建
csp.properties配置文件:
csp.base-uri='self' https://your-domain.com
- 自定义拦截器读取配置:
public class PropertyDrivenCSPInterceptor extends ContentSecurityPolicyInterceptor { private static final Properties cspProps = new Properties(); static { try (InputStream is = PropertyDrivenCSPInterceptor.class.getClassLoader().getResourceAsStream("csp.properties")) { cspProps.load(is); } catch (IOException e) { e.printStackTrace(); } } @Override protected Map<String, String> buildCspDirectives(ActionInvocation invocation) { Map<String, String> directives = super.buildCspDirectives(invocation); String baseUri = cspProps.getProperty("csp.base-uri"); if (baseUri != null) { directives.put("base-uri", baseUri); } return directives; } }
扩展:支持Action级别覆盖全局配置
如果需要某些Action单独设置base-uri,可以在自定义拦截器中优先读取Action上的CSPSettings注解配置:
@Override protected Map<String, String> buildCspDirectives(ActionInvocation invocation) { Map<String, String> directives = super.buildCspDirectives(invocation); // 优先使用Action上的CSPSettings注解配置 CSPSettings settings = invocation.getAction().getClass().getAnnotation(CSPSettings.class); if (settings != null && !settings.baseUri().isEmpty()) { directives.put("base-uri", settings.baseUri()); } else { // 无Action级配置时使用全局配置 directives.put("base-uri", "'self' https://your-domain.com"); } return directives; }
内容的提问来源于stack exchange,提问作者Erica Kane
相关产品推荐
相关产品推荐

