Spring Security 是一款安全管理框架,在SpringBoot/SpringCloud环境下可以达成0配置的方式集成,非常方便
Spring提供了一个名为DelegatingFilterProxy的过滤器实现,它允许在Servlet容器的生命周期和Spring的ApplicationContext之间架桥
这是Spring Security提供的过滤器链代理,它被包含在DelegatingFilterProxy
过滤器中,在接受请求时会经由FilterChainProxy
决定来使用哪一条SecurityFilterChain
过滤器链
这个是由FilterChainProxy
代理来决定实例的调用,这样对每一套匹配我们都可以有细致的配置,其中SecurityFilterChain
实例下的SecurityFilter
一般都是Bean
在过滤器链代理对象中可以有一个或多个过滤器链,在多个过滤器链中一个请求会匹配首个满足匹配条件的过滤器链
SecurityContext
的过滤器SecurityContextRepository
获取SecurityContext
并在请求结束后清除此SecurityContext
CsrfFilter
LogoutSuccessHandler
和LogoutHandler
/login
URL的请求AuthenticationManager
并BearerTokenAuthenticationToken
能被AuthenticationManager
验证RequestCache
上的getMatchingRequest ()
,如果方法返回一个增强的request
则会将它交给doFilter()
,如果方法返回null
将使用原始的请求,过滤器是没有效果的HttpServletRequest.authenticate(HttpServletResponse)
:允许用户确定他们是否经过身份验证,如果没有则将用户发送到登录页面HttpServletRequest.login(String, String)
:允许用户通过AuthenticationManager
进行身份验证HttpServletRequest.logout()
:允许使用配置的LogoutHandler
进行注销AsyncContext.start(Runnable)
:自动的复制从当前线程的SecurityContextHolder
找到的SecurityContext
到Runable
线程SecurityContext
中是否没有Authentication
对象,如果RememberMeServices
有被实现,则将Authentication
填充到SecurityContext
中,通过过滤器调用RememberMeServices
的autoLogin()
方法,如果该方法返回一个非空Authentication
对象则会把此对象传递给AuthenticationManager
SecurityContext
中是否没有Authentication
对象,并在需要时填充一个,默认实现是在没有Authentication
对象时创建一个匿名的Authentication
对象放入到SecurityContext
中SessionAuthenticationStrategy
来执行任何与会话相关的活动AccessDeniedException
和AuthenticationException
异常这个是过滤器链中的具体过滤器,经由SecurityFilterChain
来进行注册
Spring Security 提供了全面的身份验证功能
以下是基于servlet应用会用到的一些组件
SecurityContextHolder
获取且包含当前已认证用户的Authentication
对象信息的组件AuthenticationManager
中去提供给认证一个用户或则认证当前用户SecurityContextHolder
是SecurityContext
的获取器,他可以获取、创建SecurityContext
默认的情况下SecurityContextHolder
是使用一个ThreadLocal
来储存这些细节,这就意味着SecurityContextHolder
只会在同一线程下的方法中可用,但我们也可以通过设置来改变这个默认模式
这个SecurityContext
是从SecurityContextHolder
获取得到的,SecurityContext
包含着Authentication
认证信息对象
这个Authentication
主要用于以下两个用途
AuthenticationManager
的输入,提供用户所提供的身份验证的凭证,此时用户是未认证的,自然isAuthenticated()
是false
Authentication
是可以通过SecurityContext
获取得到这个Authentication主要包含了
UserDetails
的一个实例GrantedAuthority
是给用户赋予的权限,例如角色、范围等
GrantedAuthority
可以从Authentication.getAuthorities()
方法中获得
AuthenticationManager
是定义Spring Security的过滤器如何执行身份验证的API
ProviderManager
是最常用的AuthenticationManager
实现方式,ProviderManager
代表一个AuthenticationProvider
的集合,其中每一个AuthenticationProvider
都有机会去决定身份验证是否成功、失败、或则不下决定而交给下游的AuthenticationProvider
做决定,如果配置的AuthenticationProvider
都不能够作出决定那么将会抛出AuthenticationException
异常,代表不能处理这种身份验证
在AuthenticationProvider
的集合中,每一个AuthenticationProvider
都可以处理不同类型的身份验证,例如第一个处理的是用户名/密码,第二个处理的是SAML,他们互不影响
我们可以为ProviderManager
配置一个父AuthenticationManager
,在自身没有可处理的AuthenticationProvider
时候,将会去请求这个父AuthenticationProvider
管理器,通常这个是一个ProviderManager
实例
Authentication
进行拷贝加入缓存,保留用户凭着ProviderManager
的eraseCredentialsAfterAuthentication
属性,保留凭着我们可以将多个AuthenticationProvider
注入到ProviderManager
中,每一个AuthenticationProvider
都执行特定类型的认证
AuthenticationEntryPoint
用于发送从客户端请求凭据的HTTP响应
AbstractAuthenticationProcessingFilter
是用于验证用户凭证的基本Filter
,在认证凭证之前,Spring Security通常使用AuthenticationEntryPoint
请求凭证
大体的执行流程
AbstractAuthenticationProcessingFilter
将通过HttpServletRequest
创建一个Authentication
对象用于身份验证,这个Authentication
的类型依赖于AbstractAuthenticationProcessingFilter
的子类Authentication
传递给AuthenticationManager
进行身份验证SecurityContextHolder
会被清除RememberMeServices.loginFail
将会被调用,如果有配置的话AuthenticationFailureHandler
被调用SessionAuthenticationStrategy
收到新登录的通知Authentication
设置在SecurityContextHolder
中,随后,SecurityContextPersistenceFilter
将SecurityContext
保存到HttpSession
RememberMeServices.loginSuccess
将被调用,如果有配置的话ApplicationEventPublisher
触发一个InteractiveAuthenticationSuccessEvent
事件用户名/密码是最为常见的身份验证方式,Spring Security为此提供和非常广泛的支持
Spring Security提供了以下内置机制,用于从HttpServletRequest
读取用户名和密码
Spring Security可以通过表单中的内容获取登录所需的用户名密码,在没有任何配置的情况下是默认打开的,但是如果有任何servlet配置的情况下需要手动指定
protected void configure(HttpSecurity http) {
// 配置
http.formLogin(withDefaults());
}
对于默认HTML表单提交配置我们需要注意几点:权限对象由一个GrantedAuthority
接口表示,权限对象由AuthenticationManager
插入到Authentication
对象中,然后由AccessDecisionManager s
在进行授权决策时读取