为啥我的 loadUserByUsername 不起作用?

Posted

技术标签:

【中文标题】为啥我的 loadUserByUsername 不起作用?【英文标题】:Why is my loadUserByUsername not working?为什么我的 loadUserByUsername 不起作用? 【发布时间】:2012-06-11 15:28:57 【问题描述】:

我正在使用 Spring Security 3。我有自己的身份验证提供程序。

这是我目前所拥有的:

security-app-context.xml

<authentication-manager>
    <authentication-provider user-service-ref="detailsService" />    
</authentication-manager>

<beans:bean id="loginSuccessHandler" class="com.myapp.security.LoginSuccessHandler" />
<beans:bean id="loginFailureHandler" class="com.myapp.security.LoginFailureHandler" />
<beans:bean id="detailsService" class="com.myapp.security.UserDetailService" />

用户详细信息服务

public class UserDetailService implements UserDetailsService 

    private DataSource dataSource;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException 
        String hql = "from Users where username = :username";

        List<Users> list = null;

        try 
            IO io = new IO("common_web");
            IOQuery query = new IOQuery();
            query.setStatement(hql);
            query.setParameter(new IOParameter("username", username));

            list = io.runQuery(query);

            if (list.isEmpty()) 
                return null;
            

         catch (Exception ex) 
            ex.printStackTrace();
        

        // THIS WORKS.  I HAVE A VALID USER FROM DB
        return (UserDetails) list.get(0);
    

此代码只是一个简单的示例。在“// THIS WORKS...”这一点上,我确实有来自我们数据库的Users 记录。但是当我返回这个对象时,我仍然没有通过身份验证。

请注意,Users 是一个 Hibernate 表对象。

我错过了什么?

【问题讨论】:

【参考方案1】:

仅仅因为返回了 UserDetails 并不意味着您将通过身份验证。 DaoAuthenticationProvider 会进行许多检查以确保返回的用户应该经过身份验证。例如,它确保用户名和密码匹配、帐户未过期、帐户未锁定等。一个常见的问题是返回一个不包含任何 GrantedAuthority 的 UserDetails,这会导致 UsernamePasswordAuthenticationToken 指示用户不是已通过身份验证。

您是否尝试过为 org.springframework.security 启用调试日志记录?这可以解释什么是错的。如果您不熟悉日志记录,Spring(和 Spring Security)使用 commons-logging,您可以在 Spring 参考中找到 logging guide。

PS 正如 UserDetailsS​​ervice 接口中所述,loadUserByUsername 永远不应返回 null。而是抛出一个 UsernameNotFoundException

【讨论】:

【参考方案2】:

由于Users 类正在实现UserDetails 接口,请确保您从getAuthorities 方法返回GrantedAuthority 列表而不是null。此外,其他验证方法应返回适当的值以指示用户有效。例如:

@Override
public List<GrantedAuthority> getAuthorities() 

    return AuthorityUtils.createAuthorityList("VALID_USER_ROLE");
  
@Override
public boolean isAccountNonExpired() 
    return true;


@Override
public boolean isAccountNonLocked() 
    return true;


@Override
public boolean isCredentialsNonExpired() 
    return true;


@Override
public boolean isEnabled() 
    return true;

【讨论】:

以上是关于为啥我的 loadUserByUsername 不起作用?的主要内容,如果未能解决你的问题,请参考以下文章

什么时候调用loadUserByUsername? (春季安全)

Spring Security 2.0.6 调用 UserDetailSservice 的 loadUserByuserName 方法时

JAVA——springSecurity——自定义配置的一些补充:Anonymous匿名用户重写loadUserByUsername()方法自定义WebSecurityConfig配置等

JAVA——springSecurity自定义配置的一些补充:Anonymous匿名用户重写loadUserByUsername()方法自定义WebSecurityConfig配置等

我在哪里从 Spring Security 中获取“用户名”值以传递给 UserDetailsS​​ervice 接口的 loadUserByUsername(String username) 方法

获取'无法在grails Spring安全性休息中调用null对象上的方法loadUserByUsername()'