Spring Security + 模拟 MVC 测试 - 断言错误,重定向 URL“http://localhost/login”而不是“/login”

问题描述 投票:0回答:1

我有这样的测试

@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");

但我仍然不明白为什么在这个测试中重定向网址包含主机名,而其他则不包含

java spring spring-boot spring-security mockmvc
1个回答
0
投票

虽然不是一个明确的答案,但也许我的研究会对某人有所帮助,因为在为

/login
编写测试时这种行为有点烦人,因为该端点的行为不同。

有一些相关答案:

我认为这种行为是故意的,原因有两个

  1. 该行为仅发生在
    /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
  1. FormLoginConfigurerTests 具有
    redirectedUrl
    的断言,用于显式设置登录以测试各处的绝对值。在所有其他地方,测试都使用相对路径。

仅推测:

也许这是一个错误,或者由于历史原因而以这种方式编写 - 例如旧的 RFC 2616 声明使用绝对 uri:

位置 =“位置”“:”绝对URI

但是较新的 RFC 7231 允许相对路径(详细信息 在此答案中)。

或者可能存在一些安全问题 - 强制在登录时使用绝对 URI,以便应用程序可以控制“更多”,无论使用

http
还是
https

无论如何,我还没有找到一种方法来配置它以使其表现不同。所以现在我被迫以不同于其他端点的方式测试

/login
端点。

© www.soinside.com 2019 - 2024. All rights reserved.