spring interceptor没有为@RestController服务添加标头

时间:2018-02-16 09:37:18

标签: java spring spring-mvc http interceptor

我有以下拦截器:

public class SecurityInterceptor extends HandlerInterceptorAdapter {

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        response.addHeader("X-Frame-Options", "DENY");
    }
}

我查了一下 - 春天在每次http resquest上调用它。

我注意到奇怪的事情。它适用于这样的控制器:

@Controller
public class AdminViewController {
    @GetMapping ("data")
    public String dataTemplate() {
        return "data";
    }
}

enter image description here

但它并没有像这样向控制器添加响应头:

@RestController
@RequestMapping(Constants.MY_API_URL)
public class DataServiceController {
     @PostMapping(value = "/mapping", consumes = "application/json")
     public ResponseEntity<Void> saveMapping(@RequestBody MappingDTO mapping, HttpServletRequest request) {
        ...
        return new ResponseEntity<>(CREATED);
    }
}

enter image description here

但是我可以解释它,因为拦截器正在调用。

如何为所有请求响应添加标头?

3 个答案:

答案 0 :(得分:6)

HandlerInterceptorAdapter无法使用@ResponseBodyResponseEntity方法,因为这些方法由HttpMessageConverter处理,在调用postHandle之前写入响应,这使得它成为可能很难改变回应。

相反,您可以编写ResponseBodyAdvice并将其标记为@ControllerAdvice以添加所需的标题。

@ControllerAdvice
public class ResponseDTOFilterAdvice implements ResponseBodyAdvice<Object> {
    @Override
    public boolean supports(final MethodParameter returnType, final Class<? extends HttpMessageConverter<?>> converterType) {
        return true;
    }

    @Override
    public Object beforeBodyWrite(final Object body, final MethodParameter returnType, final MediaType selectedContentType,
        final Class<? extends HttpMessageConverter<?>> selectedConverterType, final ServerHttpRequest request,
        final ServerHttpResponse response) {
        if (body instanceof ResponseEntity) {
            ResponseEntity responseEntity = (ResponseEntity) body;
            responseEntity.getHeaders().add("X-Frame-Options", "DENY");
        }
        return body;
    }
}

答案 1 :(得分:3)

我正在创建过滤器:

public class SecurityFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest httpRequest,
                                    HttpServletResponse httpResponse,
                                    FilterChain filterChain) throws ServletException, IOException {
        httpResponse.setHeader("X-FRAME-OPTIONS", "DENY");
        filterChain.doFilter(httpRequest, httpResponse);
    }
}    

并注册:

@Configuration
public class SecurityConfiguration {
    @Bean
    public FilterRegistrationBean dawsonApiFilter() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(new SecurityFilter());
        return registration;
    }
}

答案 2 :(得分:1)

先生,对于特定的控制器,您可以尝试这个程序

    @RestController
    @RequestMapping(Constants.MY_API_URL)
     public class DataServiceController {
    @PostMapping(value = "/mapping", consumes = 
     "application/json")
     public ResponseEntity<Boolean> 
     saveMapping(@RequestBody MappingDTO mapping) {
     .........
     ...........
     ......
      HttpHeaders headers = new HttpHeaders();
      headers.addHeader("X-Frame-Options", "DENY");
       return new ResponseEntity<Boolean>(true, headers, 
        HttpStatus.OK);
     }
      }

如果您的应用程序中有spring安全性,请在安全配置文件中添加此安全性。因此,我们可以为每个请求响应全局禁用xframe选项

    http.headers().frameOptions().disable();

HandlerInterceptor的PostHandle方法并不总是非常适合与@ResponseBody和ResponseEntity方法一起使用。在这种情况下,HttpMessageConverter在调用postHandle之前写入并提交响应,这使得无法更改响应,例如添加标头。相反,应用程序可以实现ResponseBodyAdvice并将其声明为@ControllerAdvice bean或直接在RequestMappingHandlerAdapter上配置它。

https://mtyurt.net/post/spring-modify-response-headers-after-processing.html

@gstackoverflow帖子所有者已找到解决方案。我们可以参考他的解决方案。