SpringSecurity的顶层脉络以及几个核心的类
用于构建对象的接口
定义能够与HttpServletRequest匹配的筛选器链。以便决定它是否适用于该请求
实现类: DefaultSecurityFilterChain
SpringSecurity进入流程
FilterChainProxy ->根据请求决定一个SecurityFilterChain ->执行SecurityFilterChain中的一系列过滤器
主要下面三个类:
所有SecurityConfigurer首先调用其init(SecurityBuilder)方法。在调用了所有init(SecurityBuilder)方法之后,将调用每个configure(SecurityBuild)方法
AbstractConfiguredSecurityBuilder是Spring Security Config对安全构建器SecurityBuilder的抽象基类实现。它继承自安全构建器SecurityBuilder的另外一个抽象基类实现AbstractSecurityBuilder。但不同的是,AbstractSecurityBuilder约定了SecurityBuilder构建的基本框架:最多被构建一次,而AbstractConfiguredSecurityBuilder在此基础上做了如下扩展:
允许将多个安全配置器SecurityConfigurer应用到该SecurityBuilder上;
定义了构建过程的生命周期(参考生命周期状态定义BuildState);
在生命周期基础之上实现并final了基类定义的抽象方法#doBuild,将构建划分为三个主要阶段#init,#configure,#performBuild;
对 #init/#configure阶段提供了实现;
对 #init/#configure阶段提供了前置回调#beforeInit/#beforeConfigure空方法供基类扩展;
#performBuild定义为抽象方法要求子类提供实现;
登记安全构建器工作过程中需要共享使用的一些对象。
performBuild
子类必须实现此方法来构建要返回的对象。返回: 要设置的对象,如果实现允许,则返回 null
postProcess
执行对象的后处理。默认是委托给 ObjectPostProcessor。参数:对象——要发布的对象返回:可能修改的要使用的对象
无法通过配置解决的可以自己实现这个接口。
SecurityBuilder用来构建安全对象,安全对象包括:HtpSecurity、FilterChainProxy、AuthenticationManager SecurityConfigurer用来配置安全对象构建器(SecurityBuilder) ,典型的有:FormLoginConfigurer、CsrfConfigurer等
代表身份验证请求的token或者经过身份验证的principal,一旦 AuthenticationManager.authenticate(Authentication) 方法处理了请求
主要方法
尝试对传递的 Authentication 对象进行身份验证,如果成功,则返回完全填充的 Authentication 对象(包括授予的权限)。 AuthenticationManager
必须遵守以下有关异常的约定:
如果帐户被禁用并且 AuthenticationManager 可以测试此状态,则必须抛出 DisabledException。
如果帐户被锁定并且 AuthenticationManager 可以测试帐户锁定,则必须抛出 LockedException。
如果提供了不正确的凭据,则必须抛出 BadCredentialsException。
虽然上述例外是可选的,但 AuthenticationManager 必须始终测试凭据。应测试异常,如果适用,则按上述顺序抛出(即,如果帐户被禁用或锁定,则立即拒绝身份验证请求并且不执行凭据测试过程)。这可以防止针对禁用或锁定的帐户测试凭据。
参数:认证——认证请求对象返回:一个完全认证的对象,包括凭证抛出:AuthenticationException——如果认证失败
SecurityBuilder 用来创建一个AuthenticationManager。允许轻松构建内存身份验证、LDAP 身份验证、基于 JDBC 的身份验证、添加 UserDetailsService 和添加 AuthenticationProvider。
重写了AbstractConfiguredSecurityBuilder中performBuild
是 AuthenticationManager 唯一具体的实现类,主要实现了 AuthenticationManager 接口中的 authenticate
被 ProviderManager 维护在属性中
主要实现类
从 UserDetailsService 检索用户详细信息的 AuthenticationProvider 实现
重要方法:
authenticate:实现了 AuthenticationProvider 中的方法
默认不适用缓存,使用的是 session
认证没有抛出异常
AbstractAuthenticationProcessingFilter
在 UsernamePasswordAuthenticationFilter 中重写了 attemptAuthentication 方法
AbstractAuthenticationFilterConfigurer
定义与当前执行线程关联的最小安全信息的接口。安全上下文存储在SecurityContextHolder中
将给定的SecurityContext与当前执行线程关联。
此类提供了一系列静态方法,这些方法委托给SecurityContextHolderStrategy的实例
默认策略为 ThreadLocalSecurityContextHolderStrategy
针对线程存储安全上下文信息的策略。首选策略由SecurityContextHolder加载。
主要策略: ThreadLocalSecurityContextHolderStrategy
使用请求之前从配置的SecurityContextRepository获得的信息填充SecurityContextHolder,并在请求完成并清除上下文保持器后将其存储回存储库中。默认情况下,它使用HttpSessionSecurityContextRepository
使用SecurityContextRepository获取SecurityContext并在SecurityContextHolder上设置它的筛选器。除了SecurityContextRepository之外,这与SecurityContextPersistenceFilter类似。必须显式调用saveContext(SecurityContext、HttpServletRequest、Http ServletResponse)才能保存SecurityContext。这通过允许不同的身份验证机制单独选择是否应该持久化身份验证来提高效率并提供更好的灵活性。
用于在请求之间持久化SecurityContext的策略。
检测SecurityContext中是否没有Authentication对象,如果RememberMeServices实现请求,则使用remember-me身份验证令牌填充上下文。具体的RememberMeServices实现将有自己的Remember MeServices。此筛选器调用的autoLogin(HttpServletRequest,HttpServletResponse)方法。如果此方法返回一个非空的Authentication对象,它将被传递给AuthenticationManager,以便实现任何特定于身份验证的行为。生成的身份验证(如果成功)将放入SecurityContext中。如果身份验证成功,将向应用程序上下文发布InteractiveAuthenticationSuccessEvent。如果身份验证失败,则不会发布任何事件,因为这通常会通过AuthenticationManager特定的应用程序事件进行记录。通常,无论身份验证成功还是失败,都将允许请求继续
验证RememberMeAuthenticationTokens的AuthenticationProvider实现。
要成功验证,RememberMeAuthenticationToken.getKeyHash()必须匹配此类的getKey()。
表示记住的身份验证。记住的身份验证必须提供完全有效的身份验证,包括适用的GrantedAuthority。
由能够提供“记住我”服务的类实现。
RememberMeServices 实现的基类:AbstractRememberMeServices
检测用户自请求开始以来已通过身份验证,如果已通过,则调用配置的SessionAuthenticationStrategy执行任何与会话相关的活动,如激活会话固定保护机制或检查多个并发登录。
当身份验证发生时,允许对HttpSession相关行为的可插拔支持。典型的用途是确保会话存在或更改会话Id以防止会话固定攻击。
RegisterSessionAuthenticationStrategy
用于在成功身份验证后向 SessionRegistry 注册用户的策略
ConcurrentSessionControlAuthenticationStrategy
处理并发会话控制的策略。当在身份验证后调用时,它将通过比较用户已激活的会话数和配置的最大会话数值,检查是否允许该用户继续。SessionRegistry用作已验证用户和会话数据的数据源。如果用户已达到允许的最大会话数,则行为取决于exceptionIfMaxExceed属性。默认行为是使超过最大允许会话数的任何会话过期,从最近最少使用的会话开始。如果再次访问,ConcurrentSessionFilter将使过期会话无效。但是,如果exceptionIfMaxExceed设置为true,则将阻止用户启动新的身份验证会话。
CompositeSessionAuthenticationStrategy
一个SessionAuthenticationStrategy,它接受多个SessionAuthenticationStrategy实现委托给它。每个SessionAuthenticationStrategy都会依次调用。如果抛出任何异常(即SessionAuthenticationException),调用将被短路。
表示Spring Security框架内会话的记录
维护SessionInformation实例的注册表。 唯一实现类 SessionRegistryImpl
确定在 ConcurrentSessionFilter 中检测到过期会话时Concurrent会话筛选器的行为
SpringSecurity剩余的除FilterSecurityInterceptor外过滤器,包括但不限于:
检测SecurityContextHolder中是否没有Authentication对象,并在需要时用一个对象填充它。
处理筛选器链中引发的任何AccessDeniedException和AuthenticationException。这个过滤器是必要的,因为它提供了Java异常和HTTP响应之间的桥梁。它只关心维护用户界面。此筛选器不执行任何实际的安全强制。
这一整条链到底如何装配起来了,HttpSecurity到底做了什么?
DelegatingFilterProxy -> FilterChainProxy -> SecurityFilterChain ->具体的Filter
HttpSecurityConfiguration配置了基础的 HttpSecurity对象以供我们注入使用
WebSecurityConfiguration注入了我们自己的 SecurityFilterChain Bean然后添加到WebSecurity中最终由WebSecurity构建出 FilterChainProxy 来执行SpringSecurity的过滤逻辑
本节内容将先学习 AuthorizationFilter 这个用于授权的过滤器,与其相对应的还有 FilterSecurityInterceptor。 主要如下类:
使用AuthorizationManager限制对URL访问的授权筛选器。
一个授权管理器,可以确定身份验证是否可以访问特定对象。
实现类:RequestMatcherDelegatingAuthorizationManager
实现类AuthenticatedAuthorizationManager
AuthorizationManager,用于确定当前用户是否经过身份验证。
HttpServletRequest授权上下文。
AuthorizeHttpRequestsConfigurer 的内部类
用于注册RequestMatcher的基类。例如,它可能允许指定哪个RequestMatcher需要特定级别的授权。
AuthorizeHttpRequestsConfigurer 的内部类
允许为RequestMatchers配置AuthorizationManager的对象。
本节内容将攻克SpringSecurity中的终极怪兽,授权处理过滤器FilterSecurityInterceptor。
通过过滤器实现对HTTP资源执行安全处理。此安全拦截器所需的SecurityMetadataSource的类型为FilterInvocationSecurityMetadaataSource
为安全对象实现安全拦截的抽象类
保存与HTTP筛选器关联的对象。
将ConfigAttribute存储为字符串。
用于web请求授权的简单表达式配置属性。
Facade将Spring Security评估安全表达式的要求与底层表达式对象的实现隔离开来
AbstractSecurityExpressionHandler
调用内部模板方法来创建StandardEvaluationContext和SecurityExpressionRoot对象。
用于配置FilterSecurityInterceptor的基类。
创建要使用的FilterInvocationSecurityMetadataSource。实现是DefaultFilterInvocationSecurityMetadataSource
SecurityExpressionRoot
用于Spring Security表达式计算的基本根对象。
子类
AbstractConfigAttributeRequestMatcherRegistry :用于注册RequestMatcher的基类。例如,它可能允许指定哪个RequestMatcher需要特定级别的授权。
做出最终访问控制(授权)决定
实现类:AbstractAccessDecisionManager
指示类负责对授权决策进行投票。投票协调(即轮询AccessDecisionVoters、统计他们的响应并做出最终授权决定)由AccessDecisionManager执行。
只有在有拒绝票和没有赞成票的情况下才拒绝访问。如果每个AccessDecisionVoter都弃权,则该决定将基于isAllowIfAllAbstrainDecisions()属性(默认为false)
本节内容将讲解SpringSecurity的实战,实现基Token于的访问模式
本节内容将讲解SpringSecurity最后一块内容,基于方法级别的权限控制及其实现原理