You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何测试@AuthenticationPrincipal?登录接口测试重定向异常排查

问题描述

我编写了如下登录接口:

@PostMapping("/login")
public String postLogin(@AuthenticationPrincipal CustomUserDetails userDetails) {
    authService.auth(userDetails.getId());
    return "redirect:/main";
}

对应的测试方法为:

@Test
void postLogin_success() throws Exception {
    UserDTO userDTO = createUserDTO(1, "User", "user@mail.ru", "password");

    when(authService.auth(anyInt())).thenReturn(userDTO);

    mockMvc.perform(post("/login")
                    .with(csrf())
                    .principal(authenticationToken)
                    .characterEncoding("UTF-8")
                    .param("email", "user@mail.ru")
                    .param("password", "password"))
            .andDo(print())
            .andExpect(status().is3xxRedirection())
            .andExpect(redirectedUrl("/main"));
}

执行测试时出现错误:java.lang.AssertionError: Redirected URL expected:</main> but was:</login?error>,实际重定向地址为/login?error,而非预期的/main,该如何解决?

解决方案
  • 确保AuthenticationPrincipal正确注入
    测试中传入的authenticationToken必须是已认证状态,且携带有效的CustomUserDetails实例。如果authenticationToken未正确构造,会导致userDetails为null,触发Spring Security的认证失败逻辑,重定向到/login?error。构造示例:

    // 创建已认证的用户详情
    CustomUserDetails testUser = new CustomUserDetails(1, "user@mail.ru", "password");
    // 构造已认证的AuthenticationToken
    Authentication authenticationToken = new UsernamePasswordAuthenticationToken(testUser, null, Collections.emptyList());
    
  • 移除测试中多余的请求参数
    你的自定义登录接口并未接收email和password参数,而是直接从已认证的上下文获取用户信息。但测试中传入的这两个参数会触发Spring Security的默认登录过滤器优先处理请求,而非走你的自定义接口逻辑。直接删除这两行param()代码:

    // 移除以下两行
    .param("email", "user@mail.ru")
    .param("password", "password")
    
  • 检查Spring Security配置冲突
    确认Security配置中,是否将POST /login的控制权交给你的控制器,而非Spring Security的默认登录处理。可以通过指定不同的登录处理端点来避免冲突:

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                // 让Spring Security默认登录处理走其他端点
                .loginProcessingUrl("/security-login")
                .and()
            .csrf(); // 确保测试中携带的csrf令牌有效
    }
    
  • 验证AuthService的Mock是否生效
    确保测试类中用@MockBean注解注入authService,而非手动实例化。否则when(authService.auth(anyInt()))的Mock逻辑不会生效,可能抛出异常导致流程中断,触发认证失败重定向。

内容的提问来源于stack exchange,提问作者Dana Kenzhebaeva

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 19:40:05