Reputation: 224
I’ve got a Spring Boot application with java configuration. I’m only referencing spring-boot-starter-jade4j and spring-boot-starter-security in my build.gradle file. I’m trying to figure out why I can’t get a csrf token to appear. Here’s my SecurityConfig
@Configuration
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
DataSource ds;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/signup", "/js/**", "/css/**", "/terms", "/privacy", "/favicon.ico").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.logoutUrl("/logout")
.permitAll()
.and()
.csrf();
}
…
}
Here’s my login form. The CSRF hidden field shows in the source code, but the csrf token doesn’t seem to evaluate and the value is empty.
extends _base
block head
block body
#bodContent.container-fluid
.row
.col-md-4
.col-md-4
br
.panel.panel-default
.panel-body
h1 Please log in
form(method="POST", action="/login")
input(type="hidden", name='_csrf', value='#{_csrf}')
.form-group
label(for="email")
| Email address
input#username.form-control(name="username", type="email", value="")
.form-group
label(for="password")
| Password
input#password.form-control(name="password", type="password", value="")
.checkbox
label
input(type="checkbox")
| Remember me
input.btn.btn-default(type="submit")
| Submit
.col-md-4
Upvotes: 4
Views: 1065
Reputation: 20135
My suspicion is that Spring Boot does not expose the CSRF token as a model attribute, which could be expected because the token is generally exposed as a request attribute (not a model attribute). In a typical Spring MVC application, the request attributes can be exposed as model attributes by setting exposeRequestAttributes
to true
on the ViewResolver
. However, I am not sure how this can be done with the Jade4j view resolver.
There is however a workaround, which is to expose the token manually through the application configuration.
@Configuration
@EnableAutoConfiguration
public class ApplicationConfig extends WebMvcConfigurerAdapter {
public static void main(String... args) {
SpringApplication.run(ApplicationConfig.class, args);
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(csrfTokenAddingInterceptor());
}
@Bean
public HandlerInterceptor csrfTokenAddingInterceptor() {
return new HandlerInterceptorAdapter() {
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView view) {
CsrfToken token = (CsrfToken) request.getAttribute(CsrfToken.class.getName())
if (token != null) {
view.addObject(token.getParameterName(), token)
}
}
}
}
}
Now your code #{_csrf.parameterName}
and #{_csrf.token}
will work.
Note: Special credit to this answer.
Upvotes: 4