Security Authentication 架构简介
类说明
在Spring Security中,包含了很多的类,Authentication主要管理授权以及授权后用户权限等信息,主要类包含以下几种:
SecurityContextHolder
: 该类主要保存已经授权用户的详情信息SecurityContext
:从SecurityContextHolder
中获取,该类中主要包含了当前已授权用户的授权信息。包括了用户基本信息,权限、角色等信息。Authentication
: 该对象可以用作AuthenticationManager
的输入,以用作用户授权的信息依据。或者已授权的当前用户信息。GrantedAuthority
:已授权主体的权限AuthenticationManager
:该类为一个API类型,用于定义Spring Security中的Filter
如何作用于授权信息(Authentication
)ProviderManager
: 对于AuthenticationManager
的一种通用实现AuthenticationProvider
: 该类主要被ProviderManager
使用,用于指定类型授权Request Credential With AuthenticationEntryPoint
:主要用于对于客户段请求的处理,(例如:跳转到一个日志界面,或者在response中返回WWW-Authenticate
)AbstractAuthenticationProcessingFilter
:是基于Filter的一种实现,将独立的任务组装成一个整体。
SecurityContextHolder
该类主要用于创建SecurityContext对象,在该类中,包含了几种创建SecurityContext
策略,具体策略如下:
MODE_PRE_INITIALIZED
:该策略则需要自己实现,通过调用setContextHolderStrategy
设置自定义的创建策略MODE_THREADLOCAL
:该策略对应着ThreadLocalSecurityContextHolderStrategy
实现,盖实现中通过ThreadLocal
的方式共享SecurityContext
对象。MODE_INHERITABLETHREADLOCAL
:该策略对应着InheritableThreadLocalSecurityContextHolderStrategy
的实现,只是与MODE_THREADLOCAL
不同,该策略实现中使用了InheritableThreadLocal
用于共享SecurityContext
实现,因此在创建子线程的时候,也会讲对应的共享信息一同共享给子线程,达到共享的目的。MODE_GLOBAL
:该策略主要是全局共享SecurityContext
,通过GlobalSecurityContextHolderStrategy
实现,这种比较适合client的工作模式,全局唯一SecurityContext
.
SecurityContext
该类通过SecurityContextHolder
进行创建,并通过不同的策略实现是否共享。在SecurityContext中,包含了授权的基本信息(Authentication
)
Authentication
该类主要作用有两个:
- 作为
AuthenticationManager
的输入,提供认证的凭证信息(例如:用户名和密码). 当在这种场景时,isAuthenticated()
方法返回false. - 代表了当前已经授权的用户,可以通过
SecurityContext
获取当前已经授权的用户信息。
在Authentication
中,主要包含了一下信息:
principal
:代表了用户。当使用用户名/密码模式授权的时候,该值始终为UseDetails
对象credentials
:通常者代表了密码,该值在用户授权完成之后会清空,以放置密码泄露authorities
:授权通过的用户所具有的权限。GrantedAuthority
是用户的高级别的权限。例如:角色和数据范围等。
GrantedAuthority
该对象可以通过Authentication.getAuthorities()
, 一般通过该方法获取到的是一个列表。在角色模式(roles)中,我们获取到的数据大概类似于:ROLE_ADMINISTRATOR
or ROLE_HR_SUPERVISOR
。这些信息最后都可以配置到对应的类,方法或者对象实体上。在web请求中,spring security拦截请求,并希望在权限中出现对应的权限信息。
当我们使用用户名/密码方式授权的时候,权限信息则通过
UseDetailsService
来加载。
AuthenticationManager
该类定义了Spring Security的Filter如何执行Authentication
信息,该类会返回Authentication
信息,并最终设置到SecurityContextHolder
上,如果没有使用Spring Security的Filter实例,可以直接向SecurityContextHolder
上设置。
我们可以自由实现AuathenticationManager
, 但是最通用的还是ProviderManager
类
ProviderManager
该类持有了AuthenticationProvider示例的列表,在处理Authentication
信息的时候,每个类都有机会来处理,最终结果可以成功,失败或者不予以处理。当为不予以处理的时候,能够让下游的AuthenticationProvider
处理。当所有的Provider
都不能处理Authentication信息时,将会抛出ProviderNotFoundException
, 用来表示没有Provider
能够处理当前的Authentication
类型的信息。
每个AuthenticationProvider都可能处理一个或者多个类型的
Authentication
信息。
当然ProviderManager还能够设置一个父ProviderManager
对象,用以在没有AuthenticationProvider
可以处理Authentication
信息的时候,可以交由父AuthenticationProvider
处理,只是一般来说,一个父实现一般也是ProviderManager
对象实例。
当然,同时也存在多个ProviderManager
共享一个父ProviderManager
的情况,主要是因为存在多个SecurityFilterChain
对象,一般用于同一个系统有不同的认证机制导致的。
默认情况下,在用户授权完成之后,会将用户登录密码或者凭证信息情况,以防止信息泄露。这将会导致当前用户再次授权的时候会出现问题,这个时候有几种方法:
- 复制当前的授权对象信息另外储存
- 关闭自动清空凭证的配置。
eraseCredentialsAfterAuthentication = false
AuthenticationProvider
该类主要针对ProviderManager
使用,用于处理不同类型的认知。例如DaoAuthenticationProvider
用于用户名和密码的授权认证。
AuthenticationEntryPoint
在一般情况下,客户端在请求资源的时候,需要携带凭证信息以便验证身份。这个时候Spring Security不需要在response
中返回header
等信息要求客户端传入凭证信息。
但是有些情况客户端在请求需要授权的资源的时候,没有携带凭证信息,这个时候就可以通过AuthenticationEntryPoint
来实现,可以跳转到一个登录界面、或者在header中响应WWW-Authenticate
或者其他的行为。
AbstractAuthenticationProcessingFilter
在以上的图像中,每个步骤的功能如下:
- 当客户端发送凭证信息到服务端时,
AbstractAuthenticationProcessingFilter
负责从请求request
中获取必要参数,并创建Authentication对象。 - 当获取到
Authentication
对象之后,将该对象发送到AuthenticationManager
进行授权 - 当用户授权失败后,将执行一下行为:
SecurityContextHolder
负责清空上下文对象信息- 将执行
RememberMeServices.loginFail
方法,如果没有配置rememberme
,则不会执行任何操作 AuthenticationFailureHandler
被执行
- 当用户授权执行成功,将执行以下行为:
SessionAuthenticationStrategy
将被通知有一个新的登录- 接着Authentication对象将被设置到SecurityContextHolder中,
SecurityContextRepository#saveContext
方法必须被明确的调用。并且在未来请求中,将会自动绑定到SecurityContext
中 RememberMeServices.loginSuccess
方法被执行,如果没有设置rememberme,则不会执行任何操作ApplicationEventPublisher
发送一个InteractiveAuthenticationSuccessEvent
事件AuthenticationSuccessHandler
类被执行