Spring Security 提供与 Spring MVC 测试的全面集成
为了在 Spring MVC 测试中使用 Spring Security,有必要添加 Spring Security
import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.*; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration @WebAppConfiguration public class CsrfShowcaseTests { @Autowired private WebApplicationContext context; private MockMvc mvc; @Before public void setup() { mvc = MockMvcBuilders .webAppContextSetup(context) .apply(springSecurity())
Spring MVC 测试提供了一个方便的接口,称为 import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.*; 当测试任何不安全的 HTTP 方法并使用 Spring Security 的 CSRF 保护时,必须确保在请求中包括有效的 CSRF 令牌。使用以下参数指定一个有效的 CSRF 令牌作为请求参数: mvc
.perform(post("/").with(csrf()))
如果你喜欢,可以在报头中包含 CSRF 令牌来替代: mvc
.perform(post("/").with(csrf().asHeader()))
还可以使用以下测试来测试提供无效的 CSRF 令牌: mvc
.perform(post("/").with(csrf().useInvalidToken()))
通常需要将测试作为特定用户运行。有两种简单的填充用户的方法:
有多种选项可将用户关联到当前的
mvc .perform(get("/").with(user("user"))) 你可以很容易地进行定制。例如,以下操作将作为用户(不需要存在)运行,用户名为 "admin"、密码为 "pass" 以及角色为 "ROLE_USER" 和 "ROLE_ADMIN"。 mvc .perform(get("/admin").with(user("admin").password("pass").roles("USER","ADMIN")))
如果你有一个你想要使用的自定义 mvc
.perform(get("/").with(user(userDetails)))
可以使用以下方式作为匿名用户运行: mvc
.perform(get("/").with(anonymous()))
如果你与默认用户一起运行,并且希望作为匿名用户执行一些请求,则这一点尤其有用。 如果你希望使用自定义身份验证(不需要存在),你可以使用以下方法进行: mvc
.perform(get("/").with(authentication(authentication)))
你甚至可以使用以下方法自定义 mvc
.perform(get("/").with(securityContext(securityContext)))
我们还可以确保使用 mvc = MockMvcBuilders .webAppContextSetup(context) .defaultRequest(get("/").with(user("user").roles("ADMIN"))) .apply(springSecurity()) .build();
如果发现在许多测试中使用相同的用户,建议将用户移动到方法。例如,你可以在你自己命名为 public static RequestPostProcessor rob() { return user("rob").roles("ADMIN"); }
现在,你可以在 import static sample.CustomSecurityMockMvcRequestPostProcessors.*; ... mvc .perform(get("/").with(rob()))
作为使用 @Test @WithMockUser public void requestProtectedUrlWithUser() throws Exception { mvc .perform(get("/")) ... } 另外,下面将使用用户名 "user"、密码 "password" 和角色 "ROLE_ADMIN" 作为用户进行测试: @Test @WithMockUser(roles="ADMIN") public void requestProtectedUrlWithUser() throws Exception { mvc .perform(get("/")) ... }
虽然始终可以使用 HTTP 基本进行身份验证,但是记住报头名称、格式和编码值有点麻烦。现在可以使用 Spring Security 的 mvc .perform(get("/").with(httpBasic("user","password"))) 将尝试使用 HTTP 基本通过确保在 HTTP 请求中填充以下头部来使用用户名 "user" 和密码 "password" 对用户进行身份验证: Authorization: Basic dXNlcjpwYXNzd29yZA==
Spring MVC 测试还提供了一个 import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.*; 你可以很简单地使用 Spring Security 的测试支持创建一个测试基于表单的身份验证的请求。例如,下面将用用户名 "user"、密码 "password" 和有效的 CSRF 令牌向 "/login" 提交一个 POST: mvc .perform(formLogin()) 很容易定制请求。例如,以下将向 "/auth" 提交用户名 "admin"、密码 "pass" 和有效的 CSRF 令牌的 POST: mvc .perform(formLogin("/auth").user("admin").password("pass")) 我们还可以自定义用户名和密码包含的参数名。例如,上面的请求被修改为在 HTTP 参数 "u" 中包括用户名,在 HTTP 参数 "p" 中包括密码。 mvc .perform(formLogin("/auth").user("u","admin").password("p","pass"))
有时需要对请求作出各种与安全相关的断言。为了满足这一需求,Spring Security 测试支持实现 Spring MVC 测试的 import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.*;
有时,断言没有与 mvc
.perform(formLogin().password("invalid"))
.andExpect(unauthenticated());
通常我们必须断言认证用户存在。例如,我们可能想验证我们已经成功认证了。我们可以通过以下代码片段验证基于表单的登录成功: mvc .perform(formLogin()) .andExpect(authenticated()); 如果我们想断定用户的角色,我们可以改进我们以前的代码,如下所示: mvc .perform(formLogin().user("admin")) .andExpect(authenticated().withRoles("USER","ADMIN")); 或者,我们可以验证用户名: mvc .perform(formLogin().user("admin")) .andExpect(authenticated().withUsername("admin")); 我们也可以结合断言: mvc .perform(formLogin().user("admin").roles("USER","ADMIN")) .andExpect(authenticated().withUsername("admin")); 我们也可以对认证进行任意断言 mvc
.perform(formLogin())
.andExpect(authenticated().withAuthentication(auth ->
assertThat(auth).isInstanceOf(UsernamePasswordAuthenticationToken.class)));
|