Note: There may be better options for Spring 2.x.
In my case (1.5.x), FilterRegistrationBean
approach didn't add the additional headers to error pages; hence the alternative.
If you want such headers applied across all static content including error pages and regular static content (e.g. as part of a security audit/vulnerability assessment), you may have to follow a composite approach.
First, a simple utility class/method to keep the header addition uniform:
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");
}
}
This adds above headers to standard static/
resources (courtesy of 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;
}
This adds above headers to error pages:
@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
};
}
Plus, some observations regarding other approaches:
- If you apply the headers at Spring Security level, they would not appear on static content such as the welcome page (base/index HTML) and error pages. (Unless you somehow configure/modify Spring Security to include static paths as well - which would of course be unnecessary, and probably impact performance)
- If you use only a
ResourceHttpRequestHandler
to inject the headers, they will not appear Security-intercepted controller responses or (more importantly) on error pages.
- In
HandlerInterceptorAdapter
I tried configuring the headers on preHandle()
and afterCompletion()
; however they did not get applied for some scenarios - esp. for error pages.