spring interceptor不会向@RestController服务添加标头

gst*_*low 6 java spring http spring-mvc 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");
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

@Controller
public class AdminViewController {
    @GetMapping ("data")
    public String dataTemplate() {
        return "data";
    }
}
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

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

@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);
    }
}
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

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

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

sha*_*zin 6

HandlerInterceptorAdapters无法使用@ResponseBodyResponseEntity方法,因为这些是HttpMessageConverterpostHandle调用之前写入响应的处理,这使得很难更改响应.

相反,您可以编写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;
    }
}
Run Code Online (Sandbox Code Playgroud)


gst*_*low 6

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

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);
    }
}    
Run Code Online (Sandbox Code Playgroud)

并注册:

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