Spring Boot无Spring Security时配置X-Frame-Options允许iframe嵌入
解决方案
不需要完整实现Spring Security就能解决X-Frame-Options的限制,以下是几种轻量可行的方案:
1. 自定义Filter设置响应头
直接通过Spring Boot的Filter机制添加或修改响应头,无需引入额外依赖:
import javax.servlet.*; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import org.springframework.stereotype.Component; @Component public class FrameOptionsFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletResponse httpResponse = (HttpServletResponse) response; // 替换为实际父应用域名,允许其嵌入当前应用 httpResponse.setHeader("X-Frame-Options", "ALLOW-FROM https://your-parent-app.com"); // 现代浏览器更推荐使用Content-Security-Policy,兼容性更强 // httpResponse.setHeader("Content-Security-Policy", "frame-ancestors https://your-parent-app.com"); chain.doFilter(request, response); } }
2. Spring MVC拦截器设置响应头
通过HandlerInterceptor在请求处理后注入响应头:
首先编写拦截器:
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.HandlerInterceptor; public class FrameOptionsInterceptor implements HandlerInterceptor { @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { response.setHeader("X-Frame-Options", "ALLOW-FROM https://your-parent-app.com"); // 或使用CSP替代 // response.setHeader("Content-Security-Policy", "frame-ancestors https://your-parent-app.com"); } }
然后注册拦截器:
import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new FrameOptionsInterceptor()); } }
3. WildFly 20服务器端全局配置
如果希望在服务器层面统一设置,无需修改应用代码,可以修改WildFly的配置文件(standalone.xml或domain.xml):
找到<subsystem xmlns="urn:jboss:domain:undertow:12.0">节点,添加以下filter和filter-ref:
<subsystem xmlns="urn:jboss:domain:undertow:12.0"> <filters> <response-header name="frame-options-header" header-name="X-Frame-Options" header-value="ALLOW-FROM https://your-parent-app.com"/> <!-- 若使用CSP则替换为以下配置 --> <!-- <response-header name="csp-header" header-name="Content-Security-Policy" header-value="frame-ancestors https://your-parent-app.com"/> --> </filters> <server name="default-server"> <host name="default-host" alias="localhost"> <filter-ref name="frame-options-header"/> <!-- 若用CSP则添加此引用 --> <!-- <filter-ref name="csp-header"/> --> </host> </server> </subsystem>
修改后重启WildFly生效。
4. 最小化Spring Security配置(仅处理头信息)
如果愿意引入Spring Security但仅做最基础的配置,不需要完整的身份验证逻辑:
首先引入Spring Security依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
然后编写配置类,仅调整frame-options规则:
import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { // 允许所有请求(身份验证由父应用处理) http.authorizeRequests().anyRequest().permitAll() .and() // 配置允许嵌入的父应用域名 .headers().frameOptions().allowFrom("https://your-parent-app.com"); // 若无需限制域名可直接禁用(不推荐,建议指定具体域名) // .headers().frameOptions().disable(); } }
注意:
ALLOW-FROM在部分现代浏览器中兼容性有限,更推荐使用Content-Security-Policy的frame-ancestors指令,它支持多个域名,兼容性更好。
内容的提问来源于stack exchange,提问作者Osee P
相关产品推荐
相关产品推荐

