将用户对象存储在与Spring Security的会话中

A_B*_*A_B 4 java spring spring-mvc spring-security spring-boot

根据我的理解,有许多不同的方法可以在Spring Security中检索经过身份验证的用户名.

我目前通过包含Principal作为控制器方法参数来获取用户名:

@RequestMapping(value = "/dashboard", method = RequestMethod.GET)
public ModelAndView displayHomePage(ModelAndView modelAndView, Principal principal) {

  modelAndView.addObject("email", principal.getName());

  // Render template located at src/main/resources/templates/dashboard.html
  modelAndView.setViewName("dashboard");

  return modelAndView;
}
Run Code Online (Sandbox Code Playgroud)

Spring Security是否为我提供了一种简单的方法将User对象存储到会话中,以便可以通过任何控制器方法轻松检索它?

我想避免每次执行数据库查找:

// Lookup user in database by e-mail
User user = userService.findUserByEmail(principal.getName());
Run Code Online (Sandbox Code Playgroud)

我正在使用Spring Security 4.2.

rvi*_*nca 6

Spring Security为您提供了一种快速,轻松访问的静态方法:

Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String name = auth.getName();
Run Code Online (Sandbox Code Playgroud)

要么

User user = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String name = user.getUsername();
Run Code Online (Sandbox Code Playgroud)

也许你想在基础抽象类中这样做

public abstract class BaseController {
    protected User getCurrentUser() {
        return (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    }
}
...
public YourController extends BaseController {
...
}
Run Code Online (Sandbox Code Playgroud)

更新

如果要将当前经过身份验证的用户存储在会话中,则需要按照@gkatzioura的建议首次在对象中存储.

@Component
@Scope("session")
public class MySessionInfo {

    private User user;

    protected User getCurrentUser() {
        if (user == null) {
            user = userService.findUserByEmail(SecurityContextHolder.getContext().getAuthentication().getPrincipal().getName());
        }
        return user;
    }
}
Run Code Online (Sandbox Code Playgroud)

你可以在你的控制器中注入这个bean

@Autowired
private MySessionInfo mySessionInfo;
Run Code Online (Sandbox Code Playgroud)

您必须注意用户未登录时的情况,但这是另一个问题.