【问题标题】:Get UserDetails object from Security Context in Spring MVC controller从 Spring MVC 控制器的安全上下文中获取 UserDetails 对象
【发布时间】:2011-09-03 22:55:31
【问题描述】:

我正在使用 Spring Security 3 和 Spring MVC 3.05。

我想打印当前登录用户的用户名,如何在我的控制器中获取用户详细信息?

@RequestMapping(value="/index.html", method=RequestMethod.GET)
    public ModelAndView indexView(){
         UserDetails user = ?
                mv.addObject("username", user.getUsername());
        ModelAndView mv = new ModelAndView("index");
        return mv;
    }   

【问题讨论】:

    标签: java spring spring-mvc spring-security


    【解决方案1】:

    如果您已经确定用户已登录(在您的示例中,如果 /index.html 受到保护):

    UserDetails userDetails =
     (UserDetails)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    

    首先检查用户是否登录,检查当前Authentication不是AnonymousAuthenticationToken

    Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    if (!(auth instanceof AnonymousAuthenticationToken)) {
            // userDetails = auth.getPrincipal()
    }
    

    【讨论】:

    • 这给了我一个例外:java.lang.ClassCastException: java.lang.String cannot be cast to org.springframework.security.core.userdetails.UserDetails
    • 我使用 UsernamePasswordAuthenticationToken 进行身份验证,即使对于已登录的用户,它也会返回一个字符串。返回的对象可能因所使用的身份验证类型而异;适当地投射你的班级,对我来说它是字符串。
    • 我相信这不是最好的方法,因为 SecurityContextHolder 在下面使用了 ThreadLocal(参见这个问题 stackoverflow.com/questions/609826/… )。除非有人可以为这种方法提供一些实际的基准(因为除了简单的 ThreadLocal 之外还有其他策略,但我没有测试过它们)我建议改用 Farm 的答案。
    • 如果 principal 是 String,你可以使用 SecurityContextHolder.getContext().getAuthentication().getDetails()。这种方式至少对 Spring Security Saml 有效。
    【解决方案2】:

    让 Spring 3 注入来解决这个问题。

    感谢tsunade21 最简单的方法是:

     @RequestMapping(method = RequestMethod.GET)   
     public ModelAndView anyMethodNameGoesHere(Principal principal) {
            final String loggedInUserName = principal.getName();
    
     }
    

    【讨论】:

    • 太棒了。比在 SecurityContextHolder 上使用静态方法时更容易进行测试。
    【解决方案3】:

    如果您只想在页面上打印用户名,也许您会喜欢这个解决方案。它没有对象强制转换,也可以在没有 Spring Security 的情况下工作:

    @RequestMapping(value = "/index.html", method = RequestMethod.GET)
    public ModelAndView indexView(HttpServletRequest request) {
    
        ModelAndView mv = new ModelAndView("index");
    
        String userName = "not logged in"; // Any default user  name
        Principal principal = request.getUserPrincipal();
        if (principal != null) {
            userName = principal.getName();
        }
    
        mv.addObject("username", userName);
    
        // By adding a little code (same way) you can check if user has any
        // roles you need, for example:
    
        boolean fAdmin = request.isUserInRole("ROLE_ADMIN");
        mv.addObject("isAdmin", fAdmin);
    
        return mv;
    }
    

    注意添加了“HttpServletRequest 请求”参数。

    工作正常,因为 Spring 为 HttpServletRequest、Principal 等注入了自己的对象(包装器),因此您可以使用标准的 java 方法来检索用户信息。

    【讨论】:

      【解决方案4】:

      这是另一种解决方案(Spring Security 3):

      public String getLoggedUser() throws Exception {
          String name = SecurityContextHolder.getContext().getAuthentication().getName();
          return (!name.equals("anonymousUser")) ? name : null;
      }
      

      【讨论】:

        【解决方案5】:

        如果您使用的是spring security,那么您可以通过

        获取当前登录用户
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
             String name = auth.getName(); //get logged in username
        

        【讨论】:

          【解决方案6】:

          您可以使用下面的代码找出主体(登录的用户电子邮件)

            org.opensaml.saml2.core.impl.NameIDImpl principal =  
            (NameIDImpl) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
          
            String email = principal.getValue();
          

          此代码是在 SAML 之上编写的。

          【讨论】:

            猜你喜欢
            • 2018-06-04
            • 2019-06-15
            • 2016-11-12
            • 2021-06-09
            • 2013-01-27
            • 1970-01-01
            • 2015-10-06
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多