春天3,Spring Security。提取经过身份验证的用户对象

时间:2012-01-06 20:34:01

标签: spring-security

这是一个Spring Security问题。

在我的应用程序中,我有一个User实体作为域对象。该对象包含支持Spring UserDetails对象的实现。身份验证(登录/注销)过程正常。

挑战在于我需要从会话中提取该对象,以便在我的代码中做出“业务逻辑”决策。

我一直在阅读有关查询SecurityContextHolder的内容,但坦率地说,我仍然不知道什么是最好的方法,因为多个Spring版本似乎是这些讨论中的一个因素。此外,Principal对象不适合我,因为它似乎不包含任何访问级别或角色信息。

下面是一个简单的控制器来说明我的挑战。它的用户域对象是硬编码的。我需要用将从Spring Security会话获取User对象的代码替换该块。我正在寻找在Spring 3中做到这一点的最好方法。

  1. 我可以将此对象作为我的域对象获取,还是需要将其作为Spring UserDetails对象获取并手动转换它?
  2. 可以以某种方式将此安全上下文查找注入我的控制器吗?

    public class HomeController {
        @RequestMapping(value="/home.html", method=RequestMethod.GET)
        public ModelAndView getHomePage(Map<String, Object> model) {
    
            // Get current user
            User currentUser=new User();
            currentUser.setUserName("Admin");
            currentUser.setAccessLevel(UserAccessLevel.ADMINISTRATOR);
    
            // Construct HomePage bean  
            HomeBean bean=new HomeBean();
            bean.setCurrentUserName(currentUser.getUserName());
    
            // Construct list of catalogs
            Collection<String> catalogList=new ArrayList<String>();
            catalogList.add("articles");
            catalogList.add("files");
            catalogList.add("comments");
            if(currentUser.hasAdministratorAccessLevel()) {
                catalogList.add("users");
            }
            bean.setCatalogList(catalogList);
    
            // Construct and return ModelAndView
            ModelAndView mav=new ModelAndView();
            mav.setViewName(WebView.HOME_PAGE.getViewName());
            mav.addObject(bean.getBeanId(), bean);
    
            return mav;
        }
    
  3. ===更新2012-01-07 ====================================== ================

    我正在处理卢克的建议。从会话中获取UserDetails并将其转换为返回的我的域User对象的方法在我的UserService中。

    这是我的控制器:

    @Controller
    public class HomeController {
    @Autowired
    private UserService userService;
    
    @RequestMapping(value="/home.html", method=RequestMethod.GET)
    public ModelAndView getHomePage(Map<String, Object> model) {
    
        // Construct HomePage bean  
        HomeBean bean=new HomeBean();
        User currentUser=userService.getCurrentlyAuthenticatedUser();
        bean.setCurrentUserName(currentUser.getUserName());
    

    这是UserServiceImpl.getCurrentlyAuthenticatedUser()的关键代码:

    @Override
    public User getCurrentlyAuthenticatedUser() {
        User currentUser=new User();
    
        Authentication a = SecurityContextHolder.getContext().getAuthentication();
        UserDetails currentUserDetails = (UserDetails) a.getPrincipal();
        if(currentUserDetails==null) {
            return currentUser;
        }
    
        currentUser.setUserName(currentUserDetails.getUsername());
    

    这样可行,但我这样做了吗?反馈非常感谢。我仍然无法从会话中检索我的用户域对象。我正在检索Spring的UserDetails对象,并使用它构建我的域User对象,但在此过程中一些信息丢失。

2 个答案:

答案 0 :(得分:8)

通常,成功Authentication中包含的主要对象将是您的用户对象的实例。因此,要快速解决方案,请使用

Authentication a = SecurityContextHolder.getContext().getAuthentication();
User currentUser = (User)a.getPrincipal();

但是(一旦你开始工作),你可能想看看我刚才给出的答案(关于如何inject a custom security context accessor的类似问题。

答案 1 :(得分:0)

Spring还提供了一个@AuthenticationPrincipal批注,它用于解析Authentication.getPrincipal()。可以像下面这样使用...

public  ResponseEntity<UserProfileResponse>UserProfile(@AuthenticationPrincipal JwtAuthenticationToken principal){