- 整体架构
- 什么是授权
- 什么是认证
- 认证核心类
- AuthenticationManager
- Authentication
- SecurityContextHolder
- 授权核心类
- AccessDecisionManager
- AccessDecisionVoter
- ConfigAttribute
- 流程
- 安全架构
- 委托过滤器代理
- 解释概括
- 过滤器链代理
- 解释概括
- 安全过滤链
- 解释概括
- 安全过滤器
- 安全异常处理
在
简单来说就是授予用户某一个权限让用户能够通过这个权限使用某个对应的服务
什么是认证验证访问系统的用户身份
认证核心类 AuthenticationManager在Spring Security中认证是由AuthenticationManager接口来负责的,接口定义为:
public interface AuthenticationManager {
Authentication authenticate(Authentication authentication) throws AuthenticationException;
}
返回Authentication表示认证成功
返回AuthenticationException异常,表示认证失败
AuthenticationAuthenticationManager主要实现类为ProviderManager,ProviderManager中管理了众多AuthenticationProvider实例。在一次完整的认证流程中, Spring Security允许存在多个AuthenticationProvider,用来实现多种认证方式,这些AuthenticationProvider都是由ProviderManager进行统一管理的。
认证以及认证成功的信息主要是由Authentication的实现类进行保存的,其接口定义为:
public interface Authentication extends Principal, Serializable {
Collection extends GrantedAuthority> getAuthorities();
Object getCredentials();
Object getDetails();
Object getPrincipal();
boolean isAuthenticated();
void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException;
}
- getAuthorities:获取用户权限信息
- getCredentials:获取用户凭证信息, 一般指密码
- getDetails:获取用户详细信息
- getPrincipal:获取用户身份信息,用户名、用户对象等
- isAuthenticated:用户是否认证成功
SecurityContextHolder用来获取登录之后用户信息。Spring Security会将登录用户数据保存在Session中。但是,为了使用方便,Spring Security在此基础上还做了-些改进,其中最主要的一个变化就是线程绑定。当用户登录成功后,Spring Security会将登录成功的用户信息保存到SecurityContextHolder中。SecurityContextHolder 中的数据保存默认是通过ThreadLocal来实现的,使用ThreadLocal创建的变量只能被当前线程访问,不能被其他线程访问和修改,也就是用户数据和请求线程绑定在一起。当登录请求处理完毕后, Spring Security会将SecurityContextHolder中的数据拿出来保存到Session中,同时将SecurityContexHolder中的数据清空。以后每当有请求到来时,Spring Security就会先从Session中取出用户登录数据,保存到SecurityContextHolder中,方便在该请求的后续处理过程中使用,同时在请求结束时将SecurityContextHolder中的数据拿出来保存到Session 中,然后将SecuritySecurityContextHolder中的数据清空。这一策略非常方便用户在Controller、Service 层以及任何代码中获取当前登录用户数据。
授权核心类当完成认证后,接下米就是授权了。在Spring Security的授权体系中,有两个关键接口
AccessDecisionManagerAccessDecisionManager (访问决策管理器),用来决定此次访问是否被允许。
AccessDecisionVoter (访问决定投票器),投票器会检查用户是否具备应有的角色,进而投出赞成、反对或者弃权票。
AccessDecisionVoter和AccessDecisionManager都有众多的实现类,在
AccessDecisionManager中会换个遍历AccessDecisionVoter, 进而决定是否允许用户访问,因而AccessDecisionVoter和AccessDecisionManager两者的关系类似于AuthenticationProvider和ProviderManager的关系。
ConfigAttribute,用来保存授权时的角色信息
在Spring Security中,用户请求一个资源(通常是一个接口或者一 个Java方法)需要的角色会被封装成一个CnfigAttribute对象,在ConfigAttribute中只有一个getAttribute方法,该方法返回一个String 字符串,就是角色的名称。一般来说,角色名称都带有一个ROLE_前缀,投票器AccessDecisionVoter所做的事情,其实就是比较用户所具各的角色和请求某个资源所需的ConfigAtuibute之间的关系。
每个部分都会有一个解释概括,如果感觉内容很长,你可以直接看我的解释概括和截取的官方图片进行理解
委托过滤器代理Spring 提供了一个名为 DelegatingFilterProxy 的过滤器实现,它允许在 Servlet 容器的生命周期和 Spring 的 ApplicationContext 之间进行桥接。 Servlet 容器允许使用自己的标准注册过滤器,但它不知道 Spring 定义的 Bean。 DelegatingFilterProxy 可以通过标准的 Servlet 容器机制注册,但将所有工作委托给实现 Filter 的 Spring Bean。
以下 DelegatingFilterProxy 如何适应过滤器和过滤器链的图片
解释概括SpringSecurity没有改变原始的JavaWeb的过滤器生态,而是在过滤器链中的第二个过滤器替换为了DelegatingFilterProxy,他的作用就是当程序进行到该过滤器是进行一个代理转接到SpringSecurity的过滤器处理中去进行相关业务的实现,完成该业务之后需要我们进行放行,回到原始过滤器链中继续执行
过滤器链代理Spring Security 的 Servlet 支持包含在 FilterChainProxy 中,FilterChainProxy 是 Spring Security 提供的一个特殊 Filter,它允许通过 SecurityFilterChain 委托给多个 Filter 实例。 由于 FilterChainProxy 是一个 Bean,它通常被包装在一个 DelegatingFilterProxy 中。
这里相当于对单个的过滤器做了增强,采用DelegatingFilterProxy代理到SpringFIlterChain这样的安全过滤链完成一系列的过滤操作流程
安全过滤链FilterChainProxy 使用 SecurityFilterChain 来确定应该为此请求调用哪些 Spring Security Filters。
SecurityFilterChain 中的安全过滤器通常是 Bean,但它们是使用 FilterChainProxy 而不是 DelegatingFilterProxy 注册的。 FilterChainProxy 为直接注册到 Servlet 容器或 DelegatingFilterProxy 提供了许多优势。 首先,它为 Spring Security 的所有 Servlet 支持提供了一个起点。 出于这个原因,如果您尝试对 Spring Security 的 Servlet 支持进行故障排除,在 FilterChainProxy 中添加调试点是一个很好的起点。
其次,由于 FilterChainProxy 是 Spring Security 使用的核心,它可以执行不被视为可选的任务。 例如,它清除 SecurityContext 以避免内存泄漏。 它还应用 Spring Security 的 HttpFirewall 来保护应用程序免受某些类型的攻击。
此外,它在确定何时应调用 SecurityFilterChain 时提供了更大的灵活性。 在 Servlet 容器中,仅根据 URL 调用过滤器。 但是,FilterChainProxy 可以通过利用 RequestMatcher 接口根据 HttpServletRequest 中的任何内容确定调用。
实际上,FilterChainProxy 可以用来确定应该使用哪个SecurityFilterChain。 这允许为应用程序的不同部分提供完全独立的配置。
在 Multiple SecurityFilterChain 图中,FilterChainProxy 决定应该使用哪个 SecurityFilterChain。 只有第一个匹配的 SecurityFilterChain 才会被调用。 如果请求 /api/messages/ 的 URL,它将首先匹配 SecurityFilterChain0 的 /api/** 模式,因此即使在 SecurityFilterChainn 上也匹配,也只会调用 SecurityFilterChain0。 如果请求 /messages/ 的 URL,它将与 SecurityFilterChain0 的 /api/** 模式不匹配,因此 FilterChainProxy 将继续尝试每个 SecurityFilterChain。 假设没有其他,SecurityFilterChain 实例匹配 SecurityFilterChainn 将被调用。
请注意,SecurityFilterChain0 仅配置了三个安全过滤器实例。 但是,SecurityFilterChainn 配置了四个安全过滤器。 需要注意的是,每个 SecurityFilterChain 都可以是唯一的并且可以单独配置。 事实上,如果应用程序希望 Spring Security 忽略某些请求,SecurityFilterChain 可能具有零安全过滤器。
解释概括这里是列举了过滤器的特性
- FilterChainProxy 使用 SecurityFilterChain 来确定应该为此请求调用哪些 Spring Security Filters
- SecurityFilterChain 中的安全过滤器通常是 Bean实例,使用 FilterChainProxy 而不是 DelegatingFilterProxy 注册
- FilterChainProxy必须执行,且有诸多安全保护的特性帮助你保护程序
- FilterChainProxy通过RequestMatcher 接口根据 HttpServletRequest中的内容可以具体的调用某个SecurityFilterChain
- SecurityFilterChain可以有多个,每个实现的功能可以不同甚至不实现,每一个都是单独进行配置的,互不干扰
- 每次其实第一个匹配的 SecurityFilterChain 才会被调用,匹配不上才会换下一个SecurityFilterChain
使用 SecurityFilterChain API 将安全过滤器插入到 FilterChainProxy 中。 过滤器的顺序很重要。 通常不需要知道 Spring Security 的过滤器的顺序。 但是,有时知道排序是有益的
- ForceEagerSessionCreationFilter
- ChannelProcessingFilter
- WebAsyncManagerIntegrationFilter
- SecurityContextPersistenceFilter
- HeaderWriterFilter
- CorsFilter
- CsrfFilter
- LogoutFilter
- OAuth2AuthorizationRequestRedirectFilter
- Saml2WebSsoAuthenticationRequestFilter
- X509AuthenticationFilter
- AbstractPreAuthenticatedProcessingFilter
- CasAuthenticationFilter
- OAuth2LoginAuthenticationFilter
- Saml2WebSsoAuthenticationFilter
- UsernamePasswordAuthenticationFilter
- OpenIDAuthenticationFilter
- DefaultLoginPageGeneratingFilter
- DefaultLogoutPageGeneratingFilter
- ConcurrentSessionFilter
- DigestAuthenticationFilter
- BearerTokenAuthenticationFilter
- BasicAuthenticationFilter
- RequestCacheAwareFilter
- SecurityContextHolderAwareRequestFilter
- JaasApiIntegrationFilter
- RememberMeAuthenticationFilter
- AnonymousAuthenticationFilter
- OAuth2AuthorizationCodeGrantFilter
- SessionManagementFilter
- ExceptionTranslationFilter
- FilterSecurityInterceptor
- SwitchUserFilter
首先,ExceptionTranslationFilter 调用 FilterChain.doFilter(request, response) 来调用应用程序的其余部分。
如果用户未通过身份验证或者是 AuthenticationException,则开始身份验证。
SecurityContextHolder 被清除
HttpServletRequest 保存在 RequestCache 中。 当用户成功认证后,RequestCache 用于重放原始请求。
AuthenticationEntryPoint 用于从客户端请求凭据。 例如,它可能重定向到登录页面或发送 WWW-Authenticate 标头。
否则,如果是 AccessDeniedException,则拒绝访问。 调用 AccessDeniedHandler 来处理拒绝访问。



