我有这样的测试
@Test
@WithAnonymousUser
void givenNoAuthentication_whenEnteringMainPage_thenRedirectToLoginPage() throws Exception {
mockMvc.perform(get("/")).andExpect(redirectedUrl("/login"));
}
我得到了这样的断言错误:
java.lang.AssertionError: Redirected URL expected:</login> but was:<http://localhost/login>
Expected :/login
Actual :http://localhost/login
更重要的是,我还有另一个与此类似的测试,该测试测试登录用户在访问 /login 后是否被重定向到主页(“/”),并且此测试工作正常
@Test
@WithMockUser
void givenAuthentication_whenEnteringLoginPage_thenRedirectToMainPage() throws Exception {
mockMvc.perform(get("/login")).andExpect(redirectedUrl("/"));
}
这是我的 Spring 安全配置的样子
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
return httpSecurity
.authorizeHttpRequests(authorize - > authorize
.requestMatchers("/css/**").permitAll()
.requestMatchers("/js/**").permitAll()
.requestMatchers("/login").permitAll()
.requestMatchers("/register").permitAll()
.requestMatchers("/user/register").permitAll()
.anyRequest().authenticated()
)
.formLogin(form - > form
.loginPage("/login")
.defaultSuccessUrl("/", true)
)
.logout(logout - > logout
.logoutUrl("/logout")
.logoutSuccessUrl("/login")
)
.build();
}
@Bean
public static PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
如何修复我的第一个测试,为什么当几乎相同的第二个测试工作正常时它不起作用?
编辑: 我设法通过使用 .endsWith("/login") 来解决这个问题,就像这样
MvcResult result = mockMvc.perform(get("/")).andReturn();
assertThat(result.getResponse().getRedirectedUrl()).endsWith("/login");
但我仍然不明白为什么在这个测试中重定向网址包含主机名,而其他则不包含
虽然不是一个明确的答案,但也许我的研究会对某人有所帮助,因为在为
/login
编写测试时这种行为有点烦人,因为该端点的行为不同。
有一些相关答案:
我认为这种行为是故意的,原因有两个
/login
上,没有其他端点。 org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint.buildRedirectUrlToLoginPage
负责此行为,有明确的逻辑使 URL 绝对 (spring.security.web:6.2.1
):if (UrlUtils.isAbsoluteUrl(loginForm)) {
return loginForm;
}
// ...
// otherwise construct absolute URL
redirectedUrl
的断言,用于显式设置登录以测试各处的绝对值。在所有其他地方,测试都使用相对路径。也许这是一个错误,或者由于历史原因而以这种方式编写 - 例如旧的 RFC 2616 声明使用绝对 uri:
位置 =“位置”“:”绝对URI
但是较新的 RFC 7231 允许相对路径(详细信息 在此答案中)。
或者可能存在一些安全问题 - 强制在登录时使用绝对 URI,以便应用程序可以控制“更多”,无论使用
http
还是 https
。
无论如何,我还没有找到一种方法来配置它以使其表现不同。所以现在我被迫以不同于其他端点的方式测试
/login
端点。