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?
HandlerInterceptorAdapter
s 无法使用 @ResponseBody
和 ResponseEntity
方法,因为它们由 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 方法将起作用。
我有以下拦截器:
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?
HandlerInterceptorAdapter
s 无法使用 @ResponseBody
和 ResponseEntity
方法,因为它们由 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 方法将起作用。