spring interceptor doesn't add header to @RestController services
Asked Answered
V

4

11

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

I checked - spring invokes its on each http resquest.

I notice strange thing. It works fine for controllers like this:

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

enter image description here

But it doesn't add response header to controller like this:

@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

But I can't explain it because interceptor is invoking.

How can I add header for all request responses?

Vacuous answered 16/2, 2018 at 9:37 Comment(3)
@pvpkiran, I understand but it would be better to do it in the only placeVacuous
@pvpkiran, also I have method which returns deferredResult. It doesn't work expected tooVacuous
Another piece of information. If you were to return 404 or some error code instead of Created or OK, then the header is added.Gnu
V
7

It is working I've created filter:

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

and registered:

@Configuration
public class SecurityConfiguration {
    @Bean
    public FilterRegistrationBean dawsonApiFilter() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(new SecurityFilter());
        return registration;
    }
}
Vacuous answered 16/2, 2018 at 10:10 Comment(0)
D
11

HandlerInterceptorAdapters can not working with @ResponseBody and ResponseEntity methods because those are handled by HttpMessageConverter which writes to response before postHandle is called which makes it difficult to change the response.

Instead you can write a ResponseBodyAdvice and mark it as @ControllerAdvice to add the header you want.

@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;
    }
}
Dull answered 16/2, 2018 at 9:59 Comment(1)
you can response.getHeaders().add(headerName, headerValue); in beforeBodyWrite if body is not instance of ResponseEntity.Shred
V
7

It is working I've created filter:

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

and registered:

@Configuration
public class SecurityConfiguration {
    @Bean
    public FilterRegistrationBean dawsonApiFilter() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(new SecurityFilter());
        return registration;
    }
}
Vacuous answered 16/2, 2018 at 10:10 Comment(0)
G
2

Sir, For specific controller you can try this procedure

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

Or

If you have spring security in your application add this one inside security configuration file .So we can disable xframe option globally for each request response

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

Or

PostHandle method of HandlerInterceptor is not always ideally suited for use with @ResponseBody and ResponseEntity methods. In such cases an HttpMessageConverter writes to and commits the response before postHandle is called which makes it impossible to change the response, for example to add a header. Instead an application can implement ResponseBodyAdvice and either declare it as an @ControllerAdvice bean or configure it directly on RequestMappingHandlerAdapter.

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

Or

@gstackoverflow post owner already find out solution .We can refer his solution.

Generation answered 17/2, 2018 at 18:50 Comment(0)
A
0

maybe too late but u can add header on preHandle then get and post method will work.

Autoeroticism answered 15/2, 2022 at 2:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.