spring 拦截器不会将 header 添加到 @RestController 服务

spring interceptor doesn't add header to @RestController services

我有以下拦截器:

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");
    }
}

我检查过 - spring 在每次 http 请求时调用它。

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

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

但它不会像这样向控制器添加响应 header:

@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);
    }
}

但是我无法解释,因为拦截器正在调用。

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

HandlerInterceptorAdapters 无法使用 @ResponseBodyResponseEntity 方法,因为它们由 HttpMessageConverter 处理,它在调用 postHandle 之前写入响应很难更改响应。

相反,您可以写一个 ResponseBodyAdvice 并将其标记为 @ControllerAdvice 以添加您想要的 header。

@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;
    }
}

它正在工作我创建了过滤器:

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;
    }
}

先生,对于特定的控制器,您可以尝试此过程

    @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 之前写入并提交响应,这使得无法更改响应,例如添加 header。相反,应用程序可以实现 ResponseBodyAdvice 并将其声明为 @ControllerAdvice bean 或直接在 RequestMappingHandlerAdapter 上配置它。

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

@gWhosebug post 所有者已经找到解决方案。我们可以参考他的解决方案。

可能为时已晚,但您可以在 preHandle 上添加 header 然后获取,post 方法将起作用。