【问题标题】:How to add response header when reaching static content using Spring Boot?使用 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,因此该文件在浏览器中打开时没有设置预期的标头。

如何向服务器发出的每个响应添加通用响应标头,包括静态文件的响应?

【问题讨论】:

    标签: spring header response


    【解决方案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?

      【讨论】:

        猜你喜欢
        • 2017-03-01
        • 1970-01-01
        • 2016-01-17
        • 2018-02-10
        • 2017-07-19
        • 1970-01-01
        • 1970-01-01
        • 2017-04-05
        • 2017-03-25
        相关资源
        最近更新 更多