Spring Security自定义身份验证 - AuthenticationProvider与UserDetailsS​​ervice

时间:2015-07-25 20:29:15

标签: java spring spring-mvc spring-security

据我所知,当你想在Spring Security中进行自定义身份验证时,你可以实现自定义AuthenticationProvider或自定义UserDetailsService

@Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth    
            //.authenticationProvider(authProvider)  // option 1
            .userDetailsService(userDetailsService); // option 2

    }

在AuthenticationProvider中,您可以检查用户名和密码,并将Authentication与您的自定义对象一起返回。

public Authentication authenticate(Authentication authentication){
        if (checkUsernameAndPassword(authentication)) {
            CustomUserDetails userDetails = new CustomUserDetails();
            //add whatever you want to the custom user details object
            return new UsernamePasswordAuthenticationToken(userDetails, password, grantedAuths);
        } else {
            throw new BadCredentialsException("Unable to auth against third party systems");
        }
    }

UserDetailsService中,您只获得用户名,当您返回自定义UserDeatails时,框架会检查密码。

public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        CustomUserDetails user = new CustomUserDetails();
        //add whatever you want to the custom user details object
        return user;
    }

看起来两者都可以产生类似的结果。所以问题是有什么区别?何时使用一对另一对?

3 个答案:

答案 0 :(得分:27)

答案在你的问题里面。 当您使用其他身份验证系统,并且您自己的数据库/数据模型中未提供密码时,您必须使用AuthenticationProvider。例如,我参与了一个客户拥有集中认证系统(CAS)的项目,因此我的系统不知道密码,我必须实现AuthenticationProvider并将给定的密码发送给CAS,并按照答案。

但是在另一个系统中,我将密码存储在我的数据库中,所以我所要做的就是实现UserDetailsS​​ervice并检查用户是否存在于我的数据库中,spring-security必须完成剩下的工作。

答案 1 :(得分:6)

从春季安全文件来看, https://docs.spring.io/spring-security/site/docs/5.0.0.RC1/reference/htmlsingle/#overall-architecture

  

UserDetailsS​​ervice经常存在一些混淆。它纯粹是用户数据的DAO,除了将数据提供给框架内的其他组件之外,不执行任何其他功能。特别是,它不会对用户进行身份验证,这是由AuthenticationManager完成的。在许多情况下,如果您需要自定义身份验证过程,则直接实现AuthenticationProvider会更有意义。

AuthenticationProvider和UserDetailsS​​ervice有不同的用途。

AuthenticationProvider验证(比较)用户(请求)提供的用户名和密码与系统用户(这可以是任何系统,如DB维护注册用户列表)

UserDetailsS​​ervice Implementation的责任是获取与用户提供的用户名匹配的系统用户详细信息。在这里,它只是获得具有相同用户名的用户,并且不告诉应用程序认证是成功还是失败。

示例: Spring提供以下作为默认设置来验证数据库

的用户详细信息
  • AuthenticationProvider - DaoAuthenticationProvider  它扩展了AbstractUserDetailsAuthenticationProvider,它通过传递用户名,Authentication对象来调用authenticate方法
  • UserDetailsS​​ervice - JdbcDaoImpl
  • 身份验证流程
  1. DaoAuthenticationProvider的职责是验证从数据库用户请求获得的用户名和密码。
  2. 要获取相应的数据库用户,它要求UserDetailsS​​ervice Implementataion JdbcDaoImpl从数据库中获取一个UserDetail对象,其名称与请求username相同。这里JdbcDaoImpl只是从系统中获取UserDetails对象。它将发送回在DB中找到的用户或发送未找到用户的异常。
  3. 如果在DB中找到用户详细信息,则DaoAuthenticationProvider继续检查请求用户密码,并且DB找到用户密码,否则验证失败。
  4. DaoAuthenticationProvider将根据JdbcDaoImpl响应来响应用户是否经过身份验证。
  5. 看看这里更好地理解它:

    AuthenticationProvider - DaoAuthenticationProvider   延伸AbstractUserDetailsAuthenticationProvider

    UserDetailsS​​ervice - JdbcDaoImpl

    UserDetails - User

答案 2 :(得分:2)

这两者是相关的,但是被Spring Security故意分开。如果企业有多个系统,UserDetailsS​​ervice将提供由您的特定系统保存的特定用户的信息,即使认证可能由另一个系统执行。在一个简单的系统中,它们可以组合在一起。例如,数据库调用将验证用户名/密码并检索该用户的所有电子邮件,ID等。

根据Spring Security Reference: http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#getting-started

UserDetailsS​​ervice经常存在一些混淆。它纯粹是用户数据的DAO,除了将数据提供给框架内的其他组件之外,不执行任何其他功能。特别是,它不会对用户进行身份验证,这是由AuthenticationManager完成的。在许多情况下,如果您需要自定义身份验证过程,则直接实现AuthenticationProvider会更有意义。

相关问题