为什么Spring安全基于用户名而不是用户ID?

And*_*reu 6 spring spring-security spring-boot spring-oauth2

在Spring Security中,UserDetails使用用户名作为用户的标识符。我的用户模型有多种类型的标识,并且有多种身份验证方式(通过电子邮件、电话号码、Facebook 等)。

我用来AuthorizationServerEndpointsConfigurer配置我的 oauth2 端点。JdbcTokenStore存储user_name在数据库中,我需要存储的是userId. 我已经更改了JdbcTokenStore以满足我的需求,但我不明白为什么 spring 框架假设用户名是唯一标识符,我的应用程序甚至不使用用户名。

例如,TokenStoreinferfacefindTokensByClientIdAndUserName是基于用户名的,为什么不呢findTokensByClientIdAndUserId?如果我使用电子邮件或电话号码对用户进行身份验证,如何获取该用户的所有令牌?

我的用户模型示例:id, email, phone number, facebook_id, name。电子邮件、电话号码和 Facebook id 是可选的,只需其中之一。在这种情况下,用户名的最佳候选者是什么?我应该以 spring 抽象方式使用用户 id 作为用户名吗?

小智 6

不确定我是否理解整个问题,但会尽力为 UserDetailService 提供最好的解释。UserDetailsS​​ervice 的方法 loadByUsername 只是一种方法,它允许您从数据库中检索用户并将其与客户端请求中的凭据进行比较,以查看它是现有用户还是不存在的用户。尽管该方法的名称是 loadUserByUsername,但这并不意味着您必须逐字传递用户名,您可以向其传递任何参数,例如电子邮件、电话号码或身份验证所基于的任何参数。

下面是该服务的一个示例实现,其中我通过 UserRepository 调用数据库并将其作为参数电子邮件提供来识别我的用户。

@Service
public class CustomUserDetailsService implements UserDetailsService {

    private UserRepository userRepository;

    @Autowired
    public CustomUserDetailsService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// Here I am retrieving the user from my database where the primary key is 
// email
        User user = userRepository.findByEmail(username);

        if(user == null) {
            throw new UsernameNotFoundException("Username not found!");
        }

        CustomUserDetails customUserDetails = new CustomUserDetails(user);
        return customUserDetails;
    }
}
Run Code Online (Sandbox Code Playgroud)