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

如何为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:

  1. 创建csp.properties配置文件:
csp.base-uri='self' https://your-domain.com
  1. 自定义拦截器读取配置:
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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 19:01:36