Security概念

UserDetailsService 和 UserDetails

   在Spring Security中,UserDetails包含系统的用户、账户的概念。包含用户名、密码和其对应的授予权限

public interface UserDetails extends Serializable {
    Collection<? extends GrantedAuthority> getAuthorities();

    String getPassword();

    String getUsername();

    boolean isAccountNonExpired();

    boolean isAccountNonLocked();

    boolean isCredentialsNonExpired();

    boolean isEnabled();
}

  UserDetailsSevice就是当前系统中如何获取库存用户信息的服务

public interface UserDetailsService {
    UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}}

Authentication

  Spring Security中设计Authentication类对输入的用户名和密码被当做用户的主体标识和用户的鉴权凭证进行封装。

        

  Principal是用户名用于可唯一标识用户信息的属性,Credentials字段则存储密码作为用户端鉴权凭证。不使用密码而是使用其他诸如令牌之类的也可以将其视为是的鉴权凭证。 不同的验证协议可能存在不同的请求参数格式,Spring Security中也提供了常见的几种常见的封装

  

 

 

    最终鉴权服务为AuthenticationProvider

       

 

    完整的鉴权服务至少需要完成以下两个任务:

在预置的用户信息库中查找出当前需要鉴权的用户记录;
验证Authentication中的鉴权凭证和用户名与预置查询出来的是否一致。

  Spring Security自身已经提供了多种认证机制

OAuth2LoginAuthenticationProvider
CasAuthenticationProvider
JwtAuthenticationProvider

  这些AuthenticationProvider中都有针对自身不同的认证机制的业务逻辑实现,验证Authentication的鉴权凭证。AuthenticationProvider还都需要从预置的用户信息库中获取预置的用户信息才能完成比对工作。Spring Security中将获取用户预置的信息的服务

    UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;

  对比AuthenticationProvider是解决了“如何验证用户输入的用户信息与预置身份信息是否一致”,UserDetailsService是解决了“从哪里获取要对比的预置身份信息记录”。在实现UserDetailsService的时候我们不用考虑验证机制的具体实现,只要考虑从哪里获取用户信息就可以了。 如果是从缓存中可使用CachingUserDetailsService,用户信息如是基于LDAP的那么就可以使用LdapUserDetailsService,如果是基于Mybatis这种JDBC框架的就可以使用JdbcUserDetailsManager。

  UserDetailsService的服务返回的是UserDetails,AuthenticationProvider的服务返回的是Authentication。那么这个将UserDetails封装的成Authentication的逻辑是是谁负责的?在Sping Security中因为UserDetailsService只提供一个根据用户名返回用户信息的动作,其他的责任跟他都没有关系,怎么将UserDetails组装成Authentication进一步向调用者返回的工作也是由AuthenticationProvider完成的。

  ProviderManager中配置了各种鉴权服务了除了验证用户信息服务之外的配置。同时也ProviderManager也是AuthenticationManager接口的实现类,而AuthenticationManager是唯一向外的提供的用户验证服务接口。AuthenticationManager本身并不实现验证用户身份的逻辑而是委托交由其配置的AuthenticationProvider去完成。
       

  为什么还要额外有一层AuthenticationManager 的封装?如果系统又支持基于用户和密码的服务,其数据是从数据库中获取的,又支持使用Token从Redis中验证Token的用户验证服务。在这样的场景下,便只要额外在AuthenticationManager的AuthenticationProvider列表增加一个基于Token验证的AuthenticationProvider(它的UserDetailsService则是通过Redis的API实现)便可。这样的配置修改并不会影响到核心对外部暴露的服务接口和相关Authentication参数。

 

  

 

 

   

posted on 2022-07-30 08:01  溪水静幽  阅读(101)  评论(0)    收藏  举报