Spring Security配置X-Frame-Options:DENY仅对后端接口生效问题求助
问题分析
- 现象:Spring Security里配置了
frameOptions().deny(),把后端localhost:8080的端点放进iframe时,限制正常生效;但把前端localhost:3000放进iframe时完全没效果,应用照样能显示。 - 根因:查响应头发现,应用初始加载阶段没有
X-Frame-Options: DENY,只有调用API接口后才会出现这个头——说明当前Header配置仅对受保护的API请求生效,没覆盖到应用初始加载的请求(比如首页、静态资源)。
问题原因
你的HttpSecurity配置里写了.anyRequest().permitAll(),而Spring Security的Headers过滤器默认只给需要认证的请求添加安全头,那些标记为permitAll()的请求(比如初始加载的页面、静态文件)不会自动带上这些安全头。
解决办法
要让所有请求(包括无需认证的初始加载请求)都带上X-Frame-Options头,有两种可行方式:
方式一:调整Spring Security配置,覆盖所有请求
修改configure(HttpSecurity http)方法,整合Headers配置,确保所有请求都能触发安全头设置:
@Override protected void configure(HttpSecurity http) throws Exception { http.cors() .and() .headers(headers -> headers // HSTS配置 .httpStrictTransportSecurity(hsts -> hsts .maxAgeInSeconds(31536000) .includeSubDomains(true)) // 禁用内容类型嗅探 .contentTypeOptions() // XSS保护 .xssProtection() // 合并CSP规则,避免重复设置 .contentSecurityPolicy(csp -> csp.policyDirectives("script-src 'self'; frame-ancestors 'none'")) // 禁用iframe嵌入 .frameOptions(frame -> frame.deny())) .and() .csrf().disable() .formLogin().defaultSuccessUrl("/swagger-ui.html", true) .and() .authorizeRequests(auth -> auth .antMatchers(AUTH_LIST).authenticated() .antMatchers("/actuator/**").access("hasAnyRole('ADMIN') and hasIpAddress('127.0.0.1')") .anyRequest().permitAll()) .httpBasic(); }
这里合并了你原来重复的httpStrictTransportSecurity和contentSecurityPolicy配置,用lambda式写法让结构更清晰,同时保证Headers规则对所有请求生效。
方式二:自定义Filter强制添加Header
如果方式一未生效,可以写个自定义Filter,给所有响应强制加上X-Frame-Options头:
@Component public class FrameOptionsFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { response.setHeader("X-Frame-Options", "DENY"); filterChain.doFilter(request, response); } }
然后在Spring Security配置中注册这个Filter,确保它在Security过滤器之前执行:
@Override protected void configure(HttpSecurity http) throws Exception { // 其他原有配置保持不变,添加下面这行 http.addFilterBefore(new FrameOptionsFilter(), ChannelProcessingFilter.class); // ... 原有的csrf、formLogin、authorizeRequests等配置 }
验证步骤
修改配置后重启应用,先访问应用初始页面(比如localhost:8080首页),检查响应头是否包含X-Frame-Options: DENY;再尝试将前端页面放入iframe,确认浏览器是否会拦截嵌入操作。
内容的提问来源于stack exchange,提问作者Firas FOUDHAILI
相关产品推荐
相关产品推荐

