如何在使用 Spring 引导到达静态内容时添加响应 header?
How to add response header when reaching static content using Spring Boot?
向控制器添加响应 header 非常简单,如:
@RequestMapping(value = "/test", method = RequestMethod.GET)
public String test(HttpServletResponse response)
{
response.setHeader("specialheader", "Special Header");
return "ok";
}
但当用户尝试访问服务器上的静态内容(如 .css 文件)时情况并非如此,我显然不想为每个文件创建端点。
所以我尝试使用实现 ResponseBodyAdvice 的新 class (@ControllerAdvice),并覆盖 'beforeBodyWrite' 函数,我得到了每个具有端点的查询的预期结果。
这个想法来源于此link。
但是当我尝试访问服务器上的一个简单的 .css 文件时,不会调用 ControllerAdvice,因此文件在浏览器中打开时没有设置预期的 headers。
如何向服务器发出的每个响应(包括静态文件的响应)添加一般响应 header?
您必须应用过滤器。这将应用于每个 HTTP 请求的响应。
您可以在这里找到确切的答案:
How to add a filter class in Spring Boot?
注: Spring 2.x.
可能有更好的选择
在我的案例 (1.5.x) 中,FilterRegistrationBean
方法没有向错误页面添加额外的 header;因此是另一种选择。
如果您希望将此类 header 应用于 所有静态内容 ,包括错误页面 和 常规静态内容(例如安全 audit/vulnerability 评估的一部分),您可能必须遵循复合方法。
首先,一个简单的实用程序 class/method 来保持 header 添加的统一:
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");
}
}
这将 headers 添加到标准 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;
}
这会将 header 秒添加到 错误页面:
@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 安全级别应用 headers,它们将不会出现在 static 内容中,例如欢迎页面 (base/index HTML) 和错误页面。 (除非你以某种方式 configure/modify Spring 安全性也包括静态路径 - 这当然是不必要的,并且可能会影响性能)
- 如果您仅使用
ResourceHttpRequestHandler
注入 header,它们将不会出现 Security-intercepted 控制器响应或(更重要的是)错误页面。
- 在
HandlerInterceptorAdapter
中,我尝试在 preHandle()
和 afterCompletion()
上配置 header;然而,他们并没有被应用于某些场景——尤其是。对于错误页面。
向控制器添加响应 header 非常简单,如:
@RequestMapping(value = "/test", method = RequestMethod.GET)
public String test(HttpServletResponse response)
{
response.setHeader("specialheader", "Special Header");
return "ok";
}
但当用户尝试访问服务器上的静态内容(如 .css 文件)时情况并非如此,我显然不想为每个文件创建端点。
所以我尝试使用实现 ResponseBodyAdvice 的新 class (@ControllerAdvice),并覆盖 'beforeBodyWrite' 函数,我得到了每个具有端点的查询的预期结果。
这个想法来源于此link。
但是当我尝试访问服务器上的一个简单的 .css 文件时,不会调用 ControllerAdvice,因此文件在浏览器中打开时没有设置预期的 headers。
如何向服务器发出的每个响应(包括静态文件的响应)添加一般响应 header?
您必须应用过滤器。这将应用于每个 HTTP 请求的响应。
您可以在这里找到确切的答案: How to add a filter class in Spring Boot?
注: Spring 2.x.
可能有更好的选择在我的案例 (1.5.x) 中,FilterRegistrationBean
方法没有向错误页面添加额外的 header;因此是另一种选择。
如果您希望将此类 header 应用于 所有静态内容 ,包括错误页面 和 常规静态内容(例如安全 audit/vulnerability 评估的一部分),您可能必须遵循复合方法。
首先,一个简单的实用程序 class/method 来保持 header 添加的统一:
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");
}
}
这将 headers 添加到标准 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;
}
这会将 header 秒添加到 错误页面:
@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 安全级别应用 headers,它们将不会出现在 static 内容中,例如欢迎页面 (base/index HTML) 和错误页面。 (除非你以某种方式 configure/modify Spring 安全性也包括静态路径 - 这当然是不必要的,并且可能会影响性能)
- 如果您仅使用
ResourceHttpRequestHandler
注入 header,它们将不会出现 Security-intercepted 控制器响应或(更重要的是)错误页面。 - 在
HandlerInterceptorAdapter
中,我尝试在preHandle()
和afterCompletion()
上配置 header;然而,他们并没有被应用于某些场景——尤其是。对于错误页面。