Spring Security 返回来宾而不是 Authentication.getPrincipal() 的 UserDetails

Posted

技术标签:

【中文标题】Spring Security 返回来宾而不是 Authentication.getPrincipal() 的 UserDetails【英文标题】:Spring Security returning guest instead of UserDetails for Authentication.getPrincipal() 【发布时间】:2011-07-12 12:47:58 【问题描述】:

我正在尝试实现 spring security 3.1.0.M1,但我无法让我的应用程序将 Authentication.getPrincipal 设置为我的自定义 UserDetails 实现。当我尝试获取登录用户时,它总是返回“guest”的主体。请参阅下面的 getLoggedInUser 方法。

在 Users.java (UserDetails impl) 中,永远不会调用 getAuthorities 方法,也许这就是未分配 user_role 的原因。

也许我配置错误...我附上了我的实现大纲,希望有人能发现我的错误。感谢您的帮助!

public static Users getLoggedInUser() 
    Users user = null;
    Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    if (auth != null && auth.isAuthenticated()) 
        Object principal = auth.getPrincipal();
        if (principal instanceof Users) 
            user = (Users) principal;
        
    
    return user;

安全上下文文件(删除了 xml 和架构定义):

<global-method-security secured-annotations="enabled">
</global-method-security>
<http security="none" pattern="/services/rest-api/1.0/**" />
<http security="none" pattern="/preregistered/**" />
<http access-denied-page="/auth/denied.html">
    <intercept-url
        pattern="/**/*.xhtml"
        access="ROLE_NONE_GETS_ACCESS" />
    <intercept-url
        pattern="/auth/**"
        access="ROLE_ANONYMOUS,ROLE_USER" />
    <intercept-url
        pattern="/auth/*"
        access="ROLE_ANONYMOUS" />
     <intercept-url
        pattern="/**"
        access="ROLE_USER" />
    <form-login
        login-processing-url="/j_spring_security_check.html"
        login-page="/auth/login.html"
        default-target-url="/registered/home.html"
        authentication-failure-url="/auth/login.html?_dc=45" />
    <logout logout-url="/auth/logout.html"
            logout-success-url="/" />
    <anonymous username="guest" granted-authority="ROLE_ANONYMOUS"/>
    <remember-me user-service-ref="userManager" key="valid key here"/>
</http>
<!-- Configure the authentication provider -->
<authentication-manager>
    <authentication-provider user-service-ref="userManager">
            <password-encoder ref="passwordEncoder" />
    </authentication-provider>
</authentication-manager>

UserDetails 实现(Users.java):

public class Users implements Serializable, UserDetails 
    public Collection<GrantedAuthority> getAuthorities() 
     List<GrantedAuthority> auth = new ArrayList<GrantedAuthority>();
    auth.add(new GrantedAuthorityImpl("ROLE_USER"));
    return auth;

user-service-ref="userManager" (UserManagerImpl.java):

 public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException 
    Users user = null;
    try 
        user = userDAO.findByUsername(username);
     catch (DataAccessException ex) 
        throw new UsernameNotFoundException("Invalid login", ex);
    
    if (user == null) 
        throw new UsernameNotFoundException("User not found.");
    
    return user;

【问题讨论】:

【参考方案1】:

您没有在此行收到编译错误:auth.add("ROLE_USER");

我认为应该是:auth.add(new SimpleGrantedAuthority("ROLE_USER"));

【讨论】:

@Ritesh,我尝试添加“ROLE_USER”常量以使其更清晰,但我认为它产生了相反的效果。在我的版本中,我实际上使用 public static final Authority AUTHORITY_USER = new Authority("ROLE_USER"); List auth = new ArrayList(); auth.add(Authority.AUTHORITY_USER);返回授权; p @Ritesh,感谢您的回复,我已将权限类添加到最初的问题中...感谢您的帮助! @colin 我不知道为什么当 SimpleGrantedAuthority 类已经存在于框架中时你创建了授权类。此外,您没有覆盖类中的 toString() 方法。请参阅 GrantedAuthority 接口的 javadoc。它说:“GrantedAuthority 必须要么将自己表示为字符串,要么由 AccessDecisionManager 专门支持。” @Ritesh,我在 spring-security-core-3.1.0.M1.jar 中没有看到 SimpleGrantedAuthority 类,但我确实注意到了我使用的 GrantedAuthorityImpl 而不是我使用的 Authority.class有。我已经更新了上面的 Users.java getAuthorites 方法以使用这个新类,但它仍然不会被 Spring 调用。关于为什么它永远不会被执行的任何想法? @Ritesh,我创建了 Authority.java 以便我可以序列化 Users.java 对象。当我使用 GrantedAuthorityImpl 时我不能这样做,因为我得到一个例外,仅供参考。

以上是关于Spring Security 返回来宾而不是 Authentication.getPrincipal() 的 UserDetails的主要内容,如果未能解决你的问题,请参考以下文章

Spring Security 在登录失败时返回 String 作为主体而不是 UserDetails?

Spring Security 返回 403 而不是 401 并创建无效的 Redis 会话 cookie

$ http get使用AngularJS返回html而不是JSON Object Spring Security

Spring Boot + Spring Security Restful 登录

jdbcAuthentication() 而不是 inMemoryAuthentication() 不提供访问权限 - Spring Security 和 Spring Data JPA

为啥在 Spring Security 的 hasPermission 检查中使用“#post”而不是“post”