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

6

根据我的理解,在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;
}

Spring Security提供了一种简单的方式,使我可以将用户对象存储到会话中,以便任何控制器方法都可以轻松地检索它吗?

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

// Lookup user in database by e-mail
User user = userService.findUserByEmail(principal.getName());

我正在使用Spring Security 4.2。


@MatejMarconak 由任何控制器方法检索 - A_B
3
您可以像这样进行操作:Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); String currentPrincipalName = authentication.getName(); - Matej Marconak
没错,但是如何在不进行数据库查找的情况下获取整个用户对象呢?我已经更新了我的问题以使其更加清晰。 - A_B
2
您可以实现自定义的UserDetailsService,在其中返回带有所需数据的自定义UserDetails - 然后该数据应该在principal中。 - Matej Marconak
2个回答

9

Spring Security为您提供了一个快速且易于访问的静态方法:

Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String name = auth.getName();

或者

User user = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String name = user.getUsername();

也许你希望在一个基础抽象类中完成此操作。
public abstract class BaseController {
    protected User getCurrentUser() {
        return (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    }
}
...
public YourController extends BaseController {
...
}

更新

如果你想将当前已认证的用户存储在会话中,那么建议只需要第一次存储在一个对象中,如@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;
    }
}

您可以在您的控制器中注入这个Bean,例如:
@Autowired
private MySessionInfo mySessionInfo;

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


如何在控制器中根据权限为该用户添加权限? - Gajanan Kulkarni
1
你还需要添加一个代理模式,例如 @Scope(scopeName = "session", proxyMode = ScopedProxyMode.TARGET_CLASS) - stephan f

0

您始终可以使用 Spring Security 提供的方法来获取基本信息,例如名称、权限以及 Authentication.class 所提供的所有内容。

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
authentication.getAuthorities();
authentication.getName();

但是如果您需要更多信息,使用会话Bean存储信息也是一个不错的选择。

@Component
@Scope("session")
public class UserInfo { .. }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接