I want to Authenticate one of the post request body key-value pair, but I want to do the same with the help of a Interceptor/Filter. How can I do that?
Asked
Active
Viewed 1,270 times
2
-
You cannot call `response.sendError(..) after `filterChain.doFilter(request, response)` is called. Because the latter call writes the response to outputstream and hence the error. The second solution I posted seems to be working locally for me. – Suman Sep 27 '20 at 21:12
-
Get the request body using `req.getReader().lines().collect(Collectors.joining(System.lineSeparator()))` And try. – Suman Sep 27 '20 at 21:18
-
it shows getReader() has already being called for this request – Pankaj Sharma Sep 27 '20 at 21:25
-
Refer this : https://www.baeldung.com/spring-reading-httpservletrequest-multiple-times – Pankaj Sharma Sep 27 '20 at 21:29
-
Refer this : https://www.baeldung.com/spring-reading-httpservletrequest-multiple-times – Suman Sep 27 '20 at 21:41
-
Yup, I already referred that. Have mentioned in the comments above – Pankaj Sharma Sep 27 '20 at 21:47
-
But is it ok/safe to do so to solve the issue? – Pankaj Sharma Sep 27 '20 at 21:48
-
That's the ideal way to read the request body more than once. Now in your case, you want to read the requestBody(which as I observe is not recommended) within filter to take some action and then proceed to other filter(Default spring filters). Hence you need to cache the requestBody the first time you read and then pass it on to further filters. – Suman Sep 27 '20 at 21:57
-
Read request body more than once like this - https://stackoverflow.com/questions/34804205/how-can-i-read-request-body-multiple-times-in-spring-handlermethodargumentresol – Suman Sep 27 '20 at 21:58
-
I feel that should solve the issue but then it's definitely not recommend, but it seems there's no way around. – Pankaj Sharma Sep 27 '20 at 22:08
-
From the documentation of HandlerInterceptor - `As a basic guideline, fine-grained handler-related preprocessing tasks are candidates for HandlerInterceptor implementations, especially factored-out common handler code and authorization checks. On the other hand, a Filter is well-suited for request content and view content handling, like multipart forms and GZIP compression. This typically shows when one needs to map the filter to certain content types (e.g. images), or to all requests.` – Suman Sep 27 '20 at 22:11
-
Can you share the link ? so should I use filters or Handler Interceptor for my task? – Pankaj Sharma Sep 27 '20 at 22:15
-
Refer this - https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/servlet/HandlerInterceptor.html. You should try to do Auth by taking the required tokens from headers and use HandlerInterceptor to do the auth check. But for now, you have to use only Filters because your auth depends on request body. – Suman Sep 28 '20 at 06:14
3 Answers
0
You can create a custom request filter that will check the request:
public class MyFilter implements OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) {
var user = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
// do stuff you need to do here
filterChain.doFilter(request, response);
}
}
and then in your WebSecurityConfiguration class register the filter like this
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterAfter(new MyFilter(), BasicAuthenticationFilter.class);
}
}

toucheqt
- 725
- 2
- 8
- 15
-
SecurityContextHolder.getContext().getAuthentication().getPrincipal() is returning null, if I do like this, any idea? – Pankaj Sharma Sep 26 '20 at 23:56
0
You can extend HandlerInterceptorAdapter and perform your custom operations/filters on top of request by overriding preHandle()
method.
Pseudocode is here:
@Component
public class SimpleInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
// Handle your request here. In your case, authentication check should go here.
return true;
}
}
Add the SimpleInterceptor
to the registry to intercept the requests.
@Configuration
@EnableWebMvc
public class SimpleMvnConfigurer implements WebMvcConfigurer {
@Autowired
SimpleInterceptor simpleInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(simpleInterceptor);
}
}
That's all!
EDIT 1:
To send the response from preHandle
method, follow below pseudocode:
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
// Handle your request here. AIn your case, authentication check should go here.
if (!isValidAuth()) {
// Populate the response here.
try {
response.setStatus(401);
response.getWriter().write("Authentication failed.");
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
return true;
} ```

Suman
- 818
- 6
- 17
-
How can I send 401 Http error response, if the authentication I do in preHandle fails? – Pankaj Sharma Sep 27 '20 at 18:48
-
-
The problem is that I cannot read request body inside this. Since I need to check with one of the parameters inside request body Refer this link ..https://stackoverflow.com/questions/21193380/get-requestbody-and-responsebody-at-handlerinterceptor. – Pankaj Sharma Sep 27 '20 at 19:44
-
How is your authentication sent? In the request body? I was hoping, normally auth tokens are sent via headers. – Suman Sep 27 '20 at 19:53
-
yes i get access to authenticated user through. String user=SecurityContextHolder.getContext().getAuthentication().getName(), but I need to verify one of the post body parameter with this user. – Pankaj Sharma Sep 27 '20 at 20:02
-
I also tried using filters and wanted to do the same. I got access to body in filter using ContentCachingRequestWrapper, but the problem lies in sending the error in that. When I do that, it says response already committed – Pankaj Sharma Sep 27 '20 at 20:08
-
I am confused where should I do this stuff, also tried using filters in spring security filter chain, but I keep getting anonymousUseror null in SecurityContextHolder.getContext().getAuthentication().getName() . For example, refer toucheqt's answer – Pankaj Sharma Sep 27 '20 at 20:11
-
Can you share the code on how you are doing it? Because filter is the right way to resolve your problem. – Suman Sep 27 '20 at 20:11
0
You can try this with Filter.
public class SimpleFilter implements Filter {
private void throwUnauthorized(ServletResponse res) throws IOException {
HttpServletResponse response = (HttpServletResponse) res;
response.reset();
response.setHeader("Content-Type", "application/json;charset=UTF-8");
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
if (!isValidAuth(request)) {
throwUnauthorized(res);
}
chain.doFilter(req, res);
}
private boolean isValidAuth(HttpServletRequest request) {
// YOUR LOGIC GOES HERE.
return false;
}
@Override
public void destroy() {
}
@Override
public void init(FilterConfig arg0) {
}
}
Register the filter using FilterRegistrationBean
@Bean
public FilterRegistrationBean<SimpleFilter> simpleFilter() {
FilterRegistrationBean<SimpleFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new SimpleFilter());
return registrationBean;
}
Let me know if this works.

Suman
- 818
- 6
- 17
-
my class extends OncePerRequestFilter in the edit in question and I have overridden doFilterInternal method. does it matter , I mean is it different than Implementing Filter class ? – Pankaj Sharma Sep 27 '20 at 21:01
-
The issue is that I am not able to extract request body before calling do filter and I get the error : response has already been commited – Pankaj Sharma Sep 27 '20 at 21:10