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

Spring Security如何将AuthenticationProvider的UserDO传递给认证成功跳转URL

实现方案汇总

方案一:将UserDO存入Authentication的principal字段(推荐)

UsernamePasswordAuthenticationToken构造方法的第一个参数principal支持存入任意自定义对象,Spring Security会将该Authentication对象全局存储在安全上下文中,是最符合Spring Security设计规范的实现方式
修改认证逻辑,将返回的UsernamePasswordAuthenticationToken第一个参数改为UserDO对象:

@Override
public Authentication authenticate(Authentication auth) throws AuthenticationException {
  UserDO userDO = service.authenticate(auth.getName(),auth.getCredentials().toString());
  if(userDO != null){ 
    // 第一个参数直接传入userDO,而非用户名字符串
    return new UsernamePasswordAuthenticationToken(
            userDO, 
            auth.getCredentials().toString(), 
            Collections.emptyList()
    );
  }else{
    throw new BadCredentialsException("用户名或密码错误");
  }
}

在/home接口有两种方式获取UserDO:

  1. 手动从安全上下文取值
@GetMapping("/home")
public String home() {
  Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
  UserDO loginUser = (UserDO) authentication.getPrincipal();
  // 后续业务逻辑
}
  1. 用注解自动注入(更简便)
@GetMapping("/home")
public String home(@AuthenticationPrincipal UserDO loginUser) {
  // 直接使用loginUser即可
}

方案二:存入HttpSession传递

认证流程中可以通过RequestContextHolder获取当前请求对象,将UserDO存入Session后,同一个会话下的所有接口都可以直接从Session中取值
认证时将UserDO存入Session:

@Override
public Authentication authenticate(Authentication auth) throws AuthenticationException {
  UserDO userDO = service.authenticate(auth.getName(),auth.getCredentials().toString());
  if(userDO != null){ 
    // 获取当前请求对象
    HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    request.getSession().setAttribute("loginUser", userDO);
    return new UsernamePasswordAuthenticationToken(
            auth.getName(), 
            auth.getCredentials().toString(), 
            Collections.emptyList()
    );
  }
  // 异常逻辑省略
}

在/home接口取值:

@GetMapping("/home")
public String home(HttpSession session) {
  UserDO loginUser = (UserDO) session.getAttribute("loginUser");
  // 后续业务逻辑
}

方案三:自定义认证成功处理器

替换默认的成功跳转逻辑,在认证成功回调中直接将UserDO存入请求属性转发到/home接口,适合仅需要在跳转接口一次性使用UserDO的场景
首先自定义成功处理器:

@Component
public class CustomAuthSuccessHandler implements AuthenticationSuccessHandler {
  @Override
  public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
    UserDO userDO = (UserDO) authentication.getPrincipal();
    request.setAttribute("loginUser", userDO);
    // 转发到/home接口
    request.getRequestDispatcher("/home").forward(request, response);
  }
}

修改Spring Security配置,替换原来的successForwardUrl配置:

@Autowired
private CustomAuthSuccessHandler customAuthSuccessHandler;

public void configure(HttpSecurity http) throws Exception {
  http
    // 其他配置省略
    .formLogin()
    .successHandler(customAuthSuccessHandler)
  ;
}

在/home接口取值:

@GetMapping("/home")
public String home(HttpServletRequest request) {
  UserDO loginUser = (UserDO) request.getAttribute("loginUser");
  // 后续业务逻辑
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 10:18:02