使用 Spring Boot 到达静态内容时如何添加响应标头?
Posted
技术标签:
【中文标题】使用 Spring Boot 到达静态内容时如何添加响应标头?【英文标题】:How to add response header when reaching static content using Spring Boot? 【发布时间】:2017-10-02 11:34:36 【问题描述】:向控制器添加响应头很简单,例如:
@RequestMapping(value = "/test", method = RequestMethod.GET)
public String test(HttpServletResponse response)
response.setHeader("specialheader", "Special Header");
return "ok";
但当用户尝试访问服务器上的静态内容(如 .css 文件)时,情况并非如此,我显然不想为每个文件创建端点。
所以我尝试使用一个实现 ResponseBodyAdvice 的新类 (@ControllerAdvice),并覆盖“beforeBodyWrite”函数,我得到了每个具有端点的查询的预期结果。
这个想法来自link。
但是当我尝试访问服务器上的简单 .css 文件时,不会调用 ControllerAdvice,因此该文件在浏览器中打开时没有设置预期的标头。
如何向服务器发出的每个响应添加通用响应标头,包括静态文件的响应?
【问题讨论】:
【参考方案1】:注意:Spring 2.x 可能有更好的选择。
在我的情况下 (1.5.x),FilterRegistrationBean
方法没有向错误页面添加额外的标题;因此是另一种选择。
如果您希望将此类标头应用于所有静态内容,包括错误页面和常规静态内容(例如,作为安全审计/漏洞评估的一部分),您可能需要遵循复合方法。
首先,一个简单的实用程序类/方法来保持标题添加统一:
import javax.servlet.http.HttpServletResponse;
public class SecurityUtils
public static void addhtmlSecurityHeaders(HttpServletResponse response)
// some example content-security related headers
response.setHeader("X-Content-Type-Options", "nosniff");
response.setHeader("X-Frame-Options", "deny");
这会将上述标头添加到标准 static/
资源(this SO answer 提供):
@Bean
public ResourceHttpRequestHandler staticHandler()
ResourceHttpRequestHandler handler = new ResourceHttpRequestHandler()
@Override
public void setHeaders(HttpServletResponse response, Resource resource, MediaType mediaType) throws IOException
SecurityUtils.addHtmlSecurityHeaders(response);
super.setHeaders(response, resource, mediaType);
;
handler.setLocations(Collections.singletonList(new ClassPathResource("static/")));
return handler;
@Bean
public SimpleUrlHandlerMapping staticMapping()
SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
mapping.setOrder(Integer.MAX_VALUE - 2);
Properties urlProperties = new Properties();
urlProperties.put("/**", "staticHandler");
mapping.setMappings(urlProperties);
return mapping;
这会将上述标题添加到错误页面:
@Bean
public WebMvcConfigurer corsConfigurer()
return new WebMvcConfigurerAdapter()
@Override
public void addInterceptors(InterceptorRegistry registry)
registry.addInterceptor(new HandlerInterceptorAdapter()
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
SecurityUtils.addHtmlSecurityHeaders(response);
);
// .. more overrides
;
另外,关于其他方法的一些观察:
如果您在 Spring Security 级别应用标头,它们将不会出现在 静态 内容中,例如欢迎页面(基本/索引 HTML)和错误页面。 (除非您以某种方式配置/修改 Spring Security 以包含静态路径 - 这当然是不必要的,并且可能会影响性能) 如果您仅使用ResourceHttpRequestHandler
来注入标头,它们将不会出现安全拦截控制器响应或(更重要的是)错误页面上。
在HandlerInterceptorAdapter
中,我尝试在preHandle()
和afterCompletion()
上配置标题;然而,它们并没有被应用于某些场景——尤其是。用于错误页面。
【讨论】:
【参考方案2】:您必须应用过滤器。这将适用于每个 HTTP 请求的响应。
您可以在这里找到确切的答案: How to add a filter class in Spring Boot?
【讨论】:
以上是关于使用 Spring Boot 到达静态内容时如何添加响应标头?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 jar 外部的 spring boot 提供静态内容?
带有静态内容的 Spring Boot 项目在运行 jar 时生成 404
如何在 Spring Boot 2.2.6 中提供静态内容?
Spring-Boot Jersey:允许 Jersey 提供静态内容