• spring security原理-学习笔记2-核心组件


    核心组件

    AuthenticationManager,ProviderManager和AuthenticationProvider

    AuthenticationManager只是一个接口,实际中是如何运作的?如果我们需要检查多个身份验证数据库或不同身份验证服务(如数据库和LDAP服务器)的组合,该怎么办?

    Spring Security中的默认实现为ProviderManager,ProviderManager本身不处理身份验证请求,它会委托给AuthenticationProvider列表进行处理,每个列表都会被查询以查看它是否可以执行认证。每个提供程序将抛出异​​常或返回完全填充的Authentication对象。
    org.springframework.security.authentication.ProviderManager内部实现:

    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    遍历List<AuthenticationProvider> 列表{
            if(provider.supports(toTest)){
                result = provider.authenticate(authentication);
                this.copyDetails(authentication, result);
            }
    }
    this.parent.authenticate(authentication);
    eventPublisher.publishAuthenticationSuccess(result);
    }
    

    还记得我们的好朋友UserDetails和UserDetailsService吗?验证身份验证请求的最常用方法是加载相应的UserDetails并检查加载的密码与用户输入的密码。这是DaoAuthenticationProvider使用的方法(见下文)。加载的UserDetails对象 - 特别是它包含的GrantedAuthority - 将在构建完全填充的Authentication对象时使用,该对象从成功的身份验证返回并存储在SecurityContext中。
    DaoAuthenticationProvider继承org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider

    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    UserDetails user = this.userCache.getUserFromCache(username);
    if(user==null){
        user = this.retrieveUser(username, (UsernamePasswordAuthenticationToken)authentication);
    }
    this.preAuthenticationChecks.check(user);
    this.additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken)authentication);
    this.postAuthenticationChecks.check(user);
    
    Object principalToReturn = user.getUsername();
    return this.createSuccessAuthentication(principalToReturn, authentication, user);
    }
    

    AuthenticationProvider实现类:org.springframework.security.authentication.dao.DaoAuthenticationProvider内部实现

    protected final UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
    UserDetails loadedUser = this.getUserDetailsService().loadUserByUsername(username);
    if (loadedUser == null) {
       throw new InternalAuthenticationServiceException("UserDetailsService returned null, which is an interface contract violation");
    } else {
       return loadedUser;
    }
    }
    

    UserDetailsS​​ervice实现

    In-Memory Authentication

    <user-service id="userDetailsService">
    <!-- Password以{noop}为前缀,指示将其委托给passwordencoder应该使用NoOpPasswordEncoder。这是不安全的生产,但使阅读样本中更容易。通常密码应该使用BCrypt散列 -->
    <user name="jimi" password="{noop}jimispassword" authorities="ROLE_USER, ROLE_ADMIN" />
    <user name="bob" password="{noop}bobspassword" authorities="ROLE_USER" />
    </user-service>
    

    JdbcDaoImpl

    从数据库加载

    密码编码

    历史的密码编码

    • 存储密码原始文本
    • 存储通过单向散列(如SHA-256)的密码
    • 为了降低Rainbow Tables的有效性,鼓励开发人员使用salted密码
    • 现在鼓励开发人员利用自适应单向函数来存储密码。开发人员来设定不同的worker factor满足不同的安全需要,在安全和效率之间做出权衡。例如: bcrypt , PBKDF2 , scrypt , and Argon2 .

    DelegatingPasswordEncoder(spring5.0后的新特性)

    • 确保使用当前密码存储建议对密码进行编码
    • 允许验证现代和传统格式的密码
    • 允许将来升级编码

    将编码方式存入密码文本

    BCryptPasswordEncoder

    https://en.wikipedia.org/wiki/Bcrypt

    Pbkdf2PasswordEncoder

    https://en.wikipedia.org/wiki/PBKDF2

    SCryptPasswordEncoder

    https://en.wikipedia.org/wiki/Scrypt

    参考

    英文版文档
    https://docs.spring.io/spring-security/site/docs/5.0.5.RELEASE/reference/htmlsingle/#overall-architecture
    中文版文档
    https://www.springcloud.cc/spring-security.html

  • 相关阅读:
    es操作
    MySQL逻辑架构
    ceshimd
    mysql资料
    已解决 : VMware Workstation 与 Hyper-V 不兼容。请先从系统中移除 Hyper-V 角色
    MySQL数据库操作
    phpstorm配置laravel语法提示
    MySQL日志之慢查询日志(slow-log)
    456
    topcoder srm 553
  • 原文地址:https://www.cnblogs.com/victor2302/p/11750407.html
Copyright © 2020-2023  润新知