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:
- 手动从安全上下文取值
@GetMapping("/home") public String home() { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); UserDO loginUser = (UserDO) authentication.getPrincipal(); // 后续业务逻辑 }
- 用注解自动注入(更简便)
@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
相关产品推荐
相关产品推荐

