当前位置:   article > 正文

【穿针引线】基于ElAdmin项目论Spring Security的工作原理,实现前后端OAuth2单点登录,源码分析_eladmin 密码加密

eladmin 密码加密

在做单点登录功能时,在这篇文博客中分析过CAS方式登录源码,关注的是认证和授权函数,其实思想都是大同小异。在这篇博客中,基于Spring Security框架的核心类和思想进行认证和授权的源码分析,做到说透讲透。

在这里插入图片描述
ElAdmin项目的用户权限管理技术栈采用了:

  • Spring Security
  • JWT
  • BCrypt 哈希加密存储
  • RSA非对称加解密(公钥加密,私钥解密)

零、架构

Spring Security架构
Spring Security中有多个过滤器,其中一个是Authentication Filter,它启动了认证流程。一旦请求通过身份验证过滤器,用户凭据将存储在Authentication对象中。负责身份验证的是AuthenticationProvider(具有authenticate()方法的接口)。 一个Spring应用程序可以拥有多个身份验证提供者,其中一个可能使用OAuth,其他可能使用LDAP。 为了管理所有这些提供者,存在一个AuthenticationManager

认证管理器通过调用每个认证提供程序的supports()方法来查找适当的认证提供程序。 supports()方法返回布尔值。 如果返回true,则认证管理器调用其authenticate()方法。

凭据传递给身份验证程序后,它会通过UserDetailsService查找系统中现有用户,并返回UserDetails实例进行验证和身份验证。 如果成功,则返回带有Principal和Authorities的Authentication对象;否则抛出AuthenticationException异常。

一、核心类

1.1 SecurityContext 安全上下文

SecurityContextSpring Security框架中的一个核心概念,用于在应用程序中存储与安全相关的上下文信息。通过SecurityContextHolderThreadLocal,应用程序可以方便地获取和设置当前线程的SecurityContext,以确保在同一线程中的所有操作都使用同一个SecurityContext。使用SecurityContext,应用程序可以方便地获取当前用户的身份认证信息和授权信息,以实现安全访问控制和权限管理等功能。

1.2 网安适配器WebSecurityConfigurerAdapter

WebSecurityConfigurerAdapter是Spring Security框架中的一个重要组件,它是一个配置类,用于配置Spring Security的安全策略和规则,以保护应用程序的资源和服务。

WebSecurityConfigurerAdapter继承自WebSecurityConfigurer接口,它提供了一组用于配置安全策略和规则的方法,包括:

  1. configure(HttpSecurity)
    用于配置HTTP请求安全策略,包括认证、授权、跨站请求伪造(CSRF)保护、会话管理等。
  2. configure(WebSecurity)
    用于配置Web安全策略,包括静态资源的安全配置、忽略的请求等。
  3. configure(AuthenticationManagerBuilder)
    用于配置用户认证管理器,包括用户认证信息源、密码加密方式、用户角色等。

第三个配置对用户权限管理至关重要。

1.3 认证器 Authentication

在Spring Security框架中,Authentication是表示用户身份认证信息的核心接口。它包含了用户的认证凭证、权限信息等,用于表示当前用户的身份信息。在用户登录成功后,Spring Security会创建一个Authentication对象,并将其绑定到SecurityContext中,以便在后续的请求处理中使用。

Authentication接口中定义了以下方法:

  • getAuthorities(): 获取当前用户所拥有的权限信息,返回一个包含GrantedAuthority对象的Collection。
  • getCredentials(): 获取当前用户的认证凭证,通常是密码或令牌等。
  • getDetails(): 获取当前用户的详细信息,通常是额外的认证信息。
  • getPrincipal(): 获取当前用户的主体信息,通常是用户名或用户对象。
  • isAuthenticated(): 获取当前用户是否已经通过身份认证,返回一个布尔值。

认证器接口Authentication有多个实现类,如图所示。
在这里插入图片描述
ElAdmin项目中,使用的是UsernamePasswordAuthenticationToken,用户名和密码。

1.4 信息认证提供者AuthenticationProvider

Spring Security框架中,AuthenticationProvider是一个用于认证用户身份的接口。它定义了一个authenticate()方法,用于对用户提供的认证凭证进行认证,并返回一个表示用户身份认证信息的Authentication对象。如果用户提供的凭证无法通过认证,则抛出相应的异常。

1.4.1 抽象用户信息认证提供者 AbstractUserDetailsAuthenticationProvider

AbstractUserDetailsAuthenticationProvider是AuthenticationProvider接口的一个抽象实现,它提供了一些通用的用户认证逻辑,可以作为自定义AuthenticationProvider实现的基类。

AbstractUserDetailsAuthenticationProvider中的主要方法包括:

  • authenticate(Authentication authentication): 对用户提供的认证凭证进行认证,并返回一个表示用户身份认证信息的Authentication对象。如果用户提供的凭证无法通过认证,则抛出相应的异常。

  • additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication): 在用户认证成功后,对用户身份信息进行进一步的验证。

  • retrieveUser(String username, UsernamePasswordAuthenticationToken authentication): 根据用户名和认证凭证获取用户身份信息,返回一个表示用户身份信息的UserDetails对象。

1.4.2 数据库认证提供者DaoAuthenticationProvider

DaoAuthenticationProvider是Spring Security框架中用于从数据源中获取用户信息进行身份认证的AuthenticationProvider实现。它通过UserDetailsService接口获取用户信息,并使用PasswordEncoder接口对用户密码进行编码和比对。

在这里插入图片描述
retrieveUser

额外身份认证
additionalAuthenticationChecks

1.4.3 用户信息服务 UserDetailsService

在这里插入图片描述
UserDetailsService是Spring Security框架中用于获取用户信息的接口,它定义了一个loadUserByUsername()方法,用于根据用户名获取用户身份信息。

在应用程序中,可以实现UserDetailsService接口,并重写loadUserByUsername()方法,以实现自定义的用户信息获取逻辑。

ElAdmin项目中定义了实现类UserDetailsServiceImpl用于获取系统内用户信息。

在这里插入图片描述

1.5 用户相关

1.5.1 用户信息 UserDetails

UserDetails是Spring Security框架中表示用户身份信息的接口,它包含了用户的用户名、密码、权限信息等。UserDetails接口定义了以下方法:

  • getUsername(): 获取用户的用户名。

  • getPassword(): 获取用户的密码。

  • getAuthorities(): 获取用户的权限信息,返回一个包含GrantedAuthority对象的Collection。

  • isEnabled(): 获取用户是否可用,返回一个布尔值,表示用户是否已经被启用。

  • isAccountNonExpired(): 获取用户的账号是否已经过期,返回一个布尔值,表示用户的账号是否已经过期。

  • isAccountNonLocked(): 获取用户的账号是否已经被锁定,返回一个布尔值,表示用户的账号是否已经被锁定。

  • isCredentialsNonExpired(): 获取用户的凭证是否已经过期,返回一个布尔值,表示用户的凭证是否已经过期。

ElAdmin项目中定义了实现类JwtUserDto用于自定义系统内用户信息,用于丰富用户信息。

1.5.2 用户信息检查器 UserDetailsChecker

UserDetailsChecker是Spring Security框架中用于在用户身份信息被使用之前对其进行检查的接口。它定义了一个check()方法,用于检查用户身份信息是否满足一定的要求,例如用户是否已经被锁定、账户是否已过期等。

在Spring Security中,AuthenticationManager会在对用户进行认证之前调用UserDetailsChecker,以确保用户身份信息的合法性。例如,如果用户的账户已经被锁定,则UserDetailsChecker会抛出一个相应的异常,以防止用户登录。

1.6 密码编码器

1.6.1 拥有的加密类种类

PasswordEncoder是Spring Security框架中用于对用户密码进行编码和解码的接口。它定义了两个方法:encode()和matches()。

  • encode()方法
    用于对用户密码进行编码,返回一个编码后的字符串。通常情况下,可以使用BCryptPasswordEncoder或者其他实现类对用户密码进行编码,以增强密码的安全性。

  • matches()方法
    用于比较用户输入的密码和存储在数据库中的密码是否匹配。在用户登录时,Spring Security会调用matches()方法对用户输入的密码进行匹配,以确定用户是否可以登录。
    在这里插入图片描述

  • BCryptPasswordEncoder:使用BCrypt算法对用户密码进行哈希加密。

  • StandardPasswordEncoder:使用SHA-256算法对用户密码进行哈希加密,并加入随机salt值。

  • Pbkdf2PasswordEncoder:使用PBKDF2算法对用户密码进行哈希加密,并加入随机salt值。

  • MessageDigestPasswordEncoder:使用指定的消息摘要算法对用户密码进行哈希加密。

  • NoOpPasswordEncoder:不对用户密码进行加密,直接将用户密码存储在数据库中。

在ElAdmin项目中使用的是BCryptPasswordEncoder,后续我们将修改为NoOpPasswordEncoder,原因将在后续章节中阐述。

1.6.2 Hash加密编码器BCryptPasswordEncoder

BCryptPasswordEncoder是Spring Security中的一种密码编码器,它使用BCrypt算法对用户密码进行哈希加密。BCrypt算法是一种安全性较高的密码哈希算法,可以有效地防止密码被破解。

BCryptPasswordEncoder的特点:

  • 每次生成的哈希值都不同,即使用户密码相同。

  • 哈希值包含salt值,可以增强密码的安全性。

  • 可以通过设置工作因子(work factor)的值来调整算法的计算复杂度,从而进一步增强密码的安全性。

1.6.3 裸加密编码器NoOpPasswordEncoder

NoOpPasswordEncoder是Spring Security中的一种密码编码器,它不对用户密码进行加密,直接将用户密码存储在数据库中。由于NoOpPasswordEncoder不对密码进行加密,因此不推荐在生产环境中使用,因为它会导致密码泄露的风险。

二、传输和存储的加解密方式

2.1 传输加解密

ElAdmin项目中登录时,前端项目对用户输入的密码进行RSA公钥加密。
在这里插入图片描述
后端收到后,对其进行私钥解密。
在这里插入图片描述

2.2 存储加密

使用编码器BCryptPasswordEncoder对密码进行加密。

三、登录流程

四、前后端OAuth2单点登录

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/497880
推荐阅读
相关标签
  

闽ICP备14008679号