Spring 引导,Spring 安全和 Thymeleaf:将 CsrfFilter 应用于具有表单的网站
Spring Boot, Spring Security and Thymeleaf: Apply CsrfFilter to website with form
我正在使用 Thymeleaf 的 Spring 安全性,并希望在不同的站点上创建一个登录和注册表单,同时使用 CSRF 保护。保护登录站点很容易,就像下面的 WebSecurity 配置一样
@Override
protected void configure(final HttpSecurity http) throws Exception {
http
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.requestMatchers()
.antMatchers("/login", "/oauth/authorize", "/oauth/confirm_access")
.and()
.authorizeRequests()
.anyRequest()
.authenticated();
}
Spring 支持通过在配置方法中构建的安全过滤器链添加 CSRF 保护。此过滤器链包含一个 adds/evaluates CSRF 令牌的 CSRFFilter。然后,此过滤器链用于上述配置中定义的所有匹配项。可以在方法
中找到获取应用于请求的过滤器的机制 here
doFilterInternal(ServletRequest, ServletResponse, FilterChain)
问题是,如果我将“/register”站点添加到此配置中,用户将首先被重定向到“/login”站点。如果我不将它添加到上面的配置中,则不会应用提到的 FilterChain(因此不会应用 CsrfFilter)。
所以我想在“/register”站点的过滤器链中重用CsrfFilter,但我不知道该怎么做。
从所有这些我了解到问题是您希望人们无需先登录即可访问/注册。这是一个简单的修复:
@Override
protected void configure(final HttpSecurity http) throws Exception {
http
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.requestMatchers()
// add this line
.antMatchers("/register").permitAll().and
//
.antMatchers("/login", "/oauth/authorize", "/oauth/confirm_access")
.and()
.authorizeRequests()
.anyRequest()
.authenticated();
}
事实证明,Spring 安全过滤器链应用于提供给 requestMatchers().antMatchers() 的列表中提到的所有端点。
所以要对不是登录站点的站点使用 CSRF 保护,我只需将它添加到此列表,然后允许所有访问它,这样就不会重定向到登录页面。我的最终配置如下所示
@Override
protected void configure(final HttpSecurity http) throws Exception {
http.requestMatchers()
// consider these patterns for this config and the Security Filter Chain
.antMatchers("/login", "/register", "/oauth/authorize", "/oauth/confirm_access", "/oauth/token_key",
"/oauth/check_token", "/oauth/error")
.and()
// define authorization behaviour
.authorizeRequests()
// /register is allowed by anyone
.antMatchers("/register").permitAll()
// /oauth/authorize needs authentication; enables redirect to /login
.antMatchers("/oauth/authorize").authenticated()
// any other request in the patterns above are forbidden
.anyRequest().denyAll()
.and()
.formLogin()
// we have a custom login page at /login
// that is permitted to everyone
.loginPage("/login").permitAll();
}
我正在使用 Thymeleaf 的 Spring 安全性,并希望在不同的站点上创建一个登录和注册表单,同时使用 CSRF 保护。保护登录站点很容易,就像下面的 WebSecurity 配置一样
@Override
protected void configure(final HttpSecurity http) throws Exception {
http
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.requestMatchers()
.antMatchers("/login", "/oauth/authorize", "/oauth/confirm_access")
.and()
.authorizeRequests()
.anyRequest()
.authenticated();
}
Spring 支持通过在配置方法中构建的安全过滤器链添加 CSRF 保护。此过滤器链包含一个 adds/evaluates CSRF 令牌的 CSRFFilter。然后,此过滤器链用于上述配置中定义的所有匹配项。可以在方法
中找到获取应用于请求的过滤器的机制 heredoFilterInternal(ServletRequest, ServletResponse, FilterChain)
问题是,如果我将“/register”站点添加到此配置中,用户将首先被重定向到“/login”站点。如果我不将它添加到上面的配置中,则不会应用提到的 FilterChain(因此不会应用 CsrfFilter)。
所以我想在“/register”站点的过滤器链中重用CsrfFilter,但我不知道该怎么做。
从所有这些我了解到问题是您希望人们无需先登录即可访问/注册。这是一个简单的修复:
@Override
protected void configure(final HttpSecurity http) throws Exception {
http
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.requestMatchers()
// add this line
.antMatchers("/register").permitAll().and
//
.antMatchers("/login", "/oauth/authorize", "/oauth/confirm_access")
.and()
.authorizeRequests()
.anyRequest()
.authenticated();
}
事实证明,Spring 安全过滤器链应用于提供给 requestMatchers().antMatchers() 的列表中提到的所有端点。
所以要对不是登录站点的站点使用 CSRF 保护,我只需将它添加到此列表,然后允许所有访问它,这样就不会重定向到登录页面。我的最终配置如下所示
@Override
protected void configure(final HttpSecurity http) throws Exception {
http.requestMatchers()
// consider these patterns for this config and the Security Filter Chain
.antMatchers("/login", "/register", "/oauth/authorize", "/oauth/confirm_access", "/oauth/token_key",
"/oauth/check_token", "/oauth/error")
.and()
// define authorization behaviour
.authorizeRequests()
// /register is allowed by anyone
.antMatchers("/register").permitAll()
// /oauth/authorize needs authentication; enables redirect to /login
.antMatchers("/oauth/authorize").authenticated()
// any other request in the patterns above are forbidden
.anyRequest().denyAll()
.and()
.formLogin()
// we have a custom login page at /login
// that is permitted to everyone
.loginPage("/login").permitAll();
}