Thymeleaf是一个Java模板引擎,用于处理和创建HTML,XML,JavaScript,CSS和纯文本。有关Thymeleaf和Spring的介绍,请查看这篇文章。
在本文中,我们将讨论如何使用Thymeleaf应用程序在Spring MVC中防止跨站点请求伪造(CSRF)攻击。更具体地说,我们将测试HTTP POST方法的CSRF攻击。
CSRF 是一种攻击,它强制最终用户在当前经过身份验证的 Web 应用程序中执行不需要的操作。
首先,让我们看看将Thymeleaf与Spring集成所需的配置。在我们的依赖项中需要百里香板弹簧库:
org.thymeleaf
thymeleaf
3.0.11.RELEASE
org.thymeleaf
thymeleaf-spring5
3.0.11.RELEASE
Copy
请注意,对于 Spring 4 项目,必须使用thymeleaf-spring4库而不是thymeleaf-spring5。可以在此处找到最新版本的依赖项。
此外,为了使用 Spring 安全性,我们需要添加以下依赖项:
org.springframework.security
spring-security-web
5.7.3
org.springframework.security
spring-security-config
5.7.3
Copy
两个与 Spring 安全性相关的库的最新版本可在此处和此处获得。
除了这里介绍的 Thymeleaf 配置之外,我们还需要为 Spring Security 添加配置。为此,我们需要创建类:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class WebMVCSecurity extends WebSecurityConfigurerAdapter {
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user1").password("{noop}user1Pass")
.authorities("ROLE_USER");
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/resources/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.httpBasic();
}
}
Copy
有关安全配置的更多详细信息和说明,请参阅Spring 安全系列。
缺省情况下,CSRF 保护在 Java 配置中启用。为了禁用这个有用的功能,我们需要在configure(...方法:
.csrf().disable()
Copy
在XML配置中,我们需要手动指定CSRF保护,否则,它将不起作用:
Copy
另请注意,如果我们使用带有登录表单的登录页面,我们需要始终在登录表单中手动包含 CSRF 令牌作为隐藏参数包含在代码中:
Copy
对于其余表单,CSRF 令牌将自动添加到具有隐藏输入的表单中:
Copy
让我们继续讨论 HTML 文件的主要部分,包括表单操作和测试过程创建。在第一个视图中,我们尝试将新学生添加到列表中:
Add Student
Add Student
Copy
在此视图中,我们通过提供ID、姓名、性别和百分比(可选,如表单验证中所述)将学生添加到列表中。在执行此表单之前,我们需要提供用户和密码,以便在 Web 应用程序中对我们进行身份验证。
现在我们进入第二个 HTML 视图。其目的是尝试进行CSRF攻击:
Copy
我们知道操作 URLhttp://localhost:8080/spring-thymeleaf/saveStudent。黑客想要访问此页面以执行攻击。
为了进行测试,请在另一个浏览器中打开HTML文件,而无需登录应用程序。当您尝试提交表格时,我们将收到以下页面:
我们的请求被拒绝,因为我们发送的请求没有 CSRF 令牌。
请注意,HTTP会话用于存储CSRF令牌。发送请求时,Spring 会将生成的令牌与存储在会话中的令牌进行比较,以确认用户没有被黑客入侵。
如果您不想使用浏览器测试 CSRF 攻击,也可以通过快速集成测试来完成;让我们从该测试的 Spring 配置开始:
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(classes = {
WebApp.class, WebMVCConfig.class, WebMVCSecurity.class, InitSecurity.class })
public class CsrfEnabledIntegrationTest {
// configuration
}
Copy
并继续进行实际测试:
@Test
public void addStudentWithoutCSRF() throws Exception {
mockMvc.perform(post("/saveStudent").contentType(MediaType.APPLICATION_JSON)
.param("id", "1234567").param("name", "Joe").param("gender", "M")
.with(testUser())).andExpect(status().isForbidden());
}
@Test
public void addStudentWithCSRF() throws Exception {
mockMvc.perform(post("/saveStudent").contentType(MediaType.APPLICATION_JSON)
.param("id", "1234567").param("name", "Joe").param("gender", "M")
.with(testUser()).with(csrf())).andExpect(status().isOk());
}
Copy
由于缺少CSRF令牌,第一个测试将导致禁止状态,而第二个测试将正确执行。
在本文中,我们讨论了如何使用Spring Security和Thymeleaf框架防止CSRF攻击。
本教程的完整实现可以在GitHub 项目中找到。