In order to disable insecure http methods, I have used a request filter
@Component
public class MethodFilter extends OncePerRequestFilter {
private final String[] allowedMethods = new String[]{"PUT", "POST", "GET", "OPTIONS"};
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
if (Arrays.stream(allowedMethods).noneMatch(x -> x.equals(request.getMethod()))) {
response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
}
filterChain.doFilter(request, response);
}
}
This works perfectly for all methods except "TRACE". For trace method, this filter is not invoked and I get a echo back of the all the headers in response body
TRACE /error HTTP/1.1
my-header: test
accept: */*
host: localhost:8087
accept-encoding: gzip, deflate, br
connection: keep-alive
For all other methods which are not in the list I get result as expected
{
"timestamp": "2021-11-03T11:49:48.545+0000",
"status": 405,
"error": "Method Not Allowed",
"message": "DELETE method is not allowed",
"path": "/test"
}
Referring to doc it seems, trace requests are sent to frameworkservlet and processed there itself. Have tried setting spring.mvc.dispatch-trace-request=true but now the responses are clubbed like this (filter still not invoked)
{
"timestamp": "2021-11-03T11:49:48.545+0000",
"status": 405,
"error": "Method Not Allowed",
"message": "TRACE method is not allowed",
"path": "/test"
}TRACE /error HTTP/1.1
my-header: test
accept: */*
host: localhost:8087
accept-encoding: gzip, deflate, br
connection: keep-alive
My question is how can I make TRACE response as same as the other requests ?
Note: The solution in this thread did not work for me.
Edit: Found the solution. An interceptor does the trick instead of a filter
@Component
public class MethodInterceptor implements HandlerInterceptor {
private final String[] allowedMethods = new String[]{"PUT", "POST", "GET", "OPTIONS"};
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (Arrays.stream(allowedMethods).noneMatch(x -> x.equals(request.getMethod()))) {
response.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
response.setHeader("Allow", "PUT, POST, GET, OPTIONS");
response.setContentType("message/http");
response.getWriter().println(request.getMethod() + " method not allowed");
response.getWriter().flush();
return false;
}
return true;
}
}
And add the interceptor via config file
@Configuration
public class InterceptorConfiguration implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MethodInterceptor());
}
}
This needs to be used in conjunction with spring.mvc.dispatch-trace-request=true
What if you try configuring Spring Security for it ... The approach with writing the filter manually, it feels a bit low level ...
@Override
protected void configure(HttpSecurity http) throws Exception
{
http
.authorizeRequests()
// You can actually disable other methods here as well
.antMatchers(HttpMethod.TRACE,"/**").denyAll()
.httpBasic();
}
If this does not work for you ... according to the docs it says
Note that HttpServlets default TRACE processing will be applied
in any case if your controllers happen to not generate a response
of content type 'message/http' (as required for a TRACE response)
Why don't you try setting content type header to message/http when responding to a TRACE request in your filter ?
Another option is disabling this in the dispatcher servlet
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With