Im creating a project with spring using spring security but i am having problem only with my api(all controllers are working correctly with csrf). But seems like the csrf is causing problem to my api, because when i make a request to my api i get:
{"id":41,"titulo":"vineta3","creationdate":1489421003000,"URL":"http://i2.kym-cdn.com/photos/images/facebook/000/125/918/RMUBQ.png","likes":0,"dislikes":0,"descripcion":"des3"}{"timestamp":1489421218765,"status":200,"error":"OK","exception":"java.lang.IllegalStateException","message":"Cannot create a session after the response has been committed","path":"/api/vineta/41/"}
The last info:
{"timestamp":1489421218765,"status":200,"error":"OK","exception":"java.lang.IllegalStateException","message":"Cannot create a session after the response has been committed","path":"/api/vineta/41/"}
is not returning when my project has not spring secutiry. Im using the next code for my security configuration.
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
public UserRepositoryAuthenticationProvider authenticationProvider;
@Override
protected void configure(HttpSecurity http) throws Exception {
// Public pages
http.authorizeRequests().antMatchers("/").permitAll();
http.authorizeRequests().antMatchers("/login").permitAll();
http.authorizeRequests().antMatchers("/loginerror").permitAll();
http.authorizeRequests().antMatchers("/registro").permitAll();
http.authorizeRequests().antMatchers("/signup").permitAll();
http.authorizeRequests().antMatchers(HttpMethod.GET, "/api/**").permitAll();
// Private pages (all other pages)
http.authorizeRequests().antMatchers("/home").hasAnyRole("USER");
//http.authorizeRequests().antMatchers("/crearComentario/vineta/{id}").hasAnyRole("USER");
// Login form
http.formLogin().loginPage("/login");
http.formLogin().usernameParameter("username");
http.formLogin().passwordParameter("password");
http.formLogin().defaultSuccessUrl("/home");
http.formLogin().failureUrl("/loginerror");
// Logout
http.logout().logoutUrl("/logout");
http.logout().logoutSuccessUrl("/");
}
@Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
// Database authentication provider
auth.authenticationProvider(authenticationProvider);
}
}
and the next for my csrf:
@Configuration
public class CSRFHandlerConfiguration extends WebMvcConfigurerAdapter {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new CSRFHandlerInterceptor());
}
}
class CSRFHandlerInterceptor extends HandlerInterceptorAdapter {
@Override
public void postHandle(final HttpServletRequest request,
final HttpServletResponse response, final Object handler,
final ModelAndView modelAndView) throws Exception {
CsrfToken token = (CsrfToken) request.getAttribute("_csrf");
modelAndView.addObject("token", token.getToken());
}
}
In the console, i can see the follow logs:
at
org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.0.32.jar:8.0.32]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_25]
Caused by: java.lang.IllegalStateException: Cannot create a session after the response has been committed
at org.apache.catalina.connector.Request.doGetSession(Request.java:2928) ~[tomcat-embed-core-8.0.32.jar:8.0.32]
Im not using SingleTransactionsController, this can be the problem?
4
Answers
I don’t understand why you use
CSRFHandlerInterceptor
, but if you want to disable CRSF only for API, I have two solutions:You can inject a
requireCsrfProtectionMatcher
to CSRF filter, for example:The default matcher is method matcher, and the second matcher is used for not
/api/
request.You can create a new Spring Security config only for
/api
, and set the order before default Spring Security config, match the API URL without CSRF:Csrf settings are global in Spring Security
This can help:
If your API uses something other than a session cookie for authentication, like basic auth or an API token, then a simple way to allow just those requests through is:
Another way to enable security for both API and Web is to include this in your SecurityConfig class: