SpringSecurity系列——授权与认证概述,安全架构day2-2(源于官网5.7.2版本)

181 篇文章 3 订阅
24 篇文章 31 订阅

整体架构

<Spring Security> 的架构设计中,认证<Authentication>和授权<Authorization>是分开的,无论使用什么样的认证方式。都不会影响授权,这是两个独立的存在,这种独立带来的好处之一,就是可以非常方便地整合一些外部的解决方案。
在这里插入图片描述

什么是授权

简单来说就是授予用户某一个权限让用户能够通过这个权限使用某个对应的服务

什么是认证

验证访问系统的用户身份

认证核心类

AuthenticationManager

在Spring Security中认证是由AuthenticationManager接口来负责的,接口定义为:

public interface AuthenticationManager {
    Authentication authenticate(Authentication authentication) throws AuthenticationException;
}

返回Authentication表示认证成功
返回AuthenticationException异常,表示认证失败

AuthenticationManager主要实现类为ProviderManager,ProviderManager中管理了众多AuthenticationProvider实例。在一次完整的认证流程中, Spring Security允许存在多个AuthenticationProvider,用来实现多种认证方式,这些AuthenticationProvider都是由ProviderManager进行统一管理的。

Authentication

认证以及认证成功的信息主要是由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;
}
  1. getAuthorities:获取用户权限信息
  2. getCredentials:获取用户凭证信息, 一般指密码
  3. getDetails:获取用户详细信息
  4. getPrincipal:获取用户身份信息,用户名、用户对象等
  5. isAuthenticated:用户是否认证成功

SecurityContextHolder

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的授权体系中,有两个关键接口

AccessDecisionManager

AccessDecisionManager (访问决策管理器),用来决定此次访问是否被允许。
在这里插入图片描述

AccessDecisionVoter

AccessDecisionVoter (访问决定投票器),投票器会检查用户是否具备应有的角色,进而投出赞成、反对或者弃权票。
在这里插入图片描述
AccessDecisionVoter和AccessDecisionManager都有众多的实现类,在
AccessDecisionManager中会换个遍历AccessDecisionVoter, 进而决定是否允许用户访问,因而AccessDecisionVoter和AccessDecisionManager两者的关系类似于AuthenticationProvider和ProviderManager的关系。

ConfigAttribute

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 可能具有零安全过滤器。

解释概括

这里是列举了过滤器的特性

  1. FilterChainProxy 使用 SecurityFilterChain 来确定应该为此请求调用哪些 Spring Security Filters
  2. SecurityFilterChain 中的安全过滤器通常是 Bean实例,使用 FilterChainProxy 而不是 DelegatingFilterProxy 注册
  3. FilterChainProxy必须执行,且有诸多安全保护的特性帮助你保护程序
  4. FilterChainProxy通过RequestMatcher 接口根据 HttpServletRequest中的内容可以具体的调用某个SecurityFilterChain
  5. SecurityFilterChain可以有多个,每个实现的功能可以不同甚至不实现,每一个都是单独进行配置的,互不干扰
  6. 每次其实第一个匹配的 SecurityFilterChain 才会被调用,匹配不上才会换下一个SecurityFilterChain

安全过滤器

使用 SecurityFilterChain API 将安全过滤器插入到 FilterChainProxy 中。 过滤器的顺序很重要。 通常不需要知道 Spring Security 的过滤器的顺序。 但是,有时知道排序是有益的

  1. ForceEagerSessionCreationFilter
  2. ChannelProcessingFilter
  3. WebAsyncManagerIntegrationFilter
  4. SecurityContextPersistenceFilter
  5. HeaderWriterFilter
  6. CorsFilter
  7. CsrfFilter
  8. LogoutFilter
  9. OAuth2AuthorizationRequestRedirectFilter
  10. Saml2WebSsoAuthenticationRequestFilter
  11. X509AuthenticationFilter
  12. AbstractPreAuthenticatedProcessingFilter
  13. CasAuthenticationFilter
  14. OAuth2LoginAuthenticationFilter
  15. Saml2WebSsoAuthenticationFilter
  16. UsernamePasswordAuthenticationFilter
  17. OpenIDAuthenticationFilter
  18. DefaultLoginPageGeneratingFilter
  19. DefaultLogoutPageGeneratingFilter
  20. ConcurrentSessionFilter
  21. DigestAuthenticationFilter
  22. BearerTokenAuthenticationFilter
  23. BasicAuthenticationFilter
  24. RequestCacheAwareFilter
  25. SecurityContextHolderAwareRequestFilter
  26. JaasApiIntegrationFilter
  27. RememberMeAuthenticationFilter
  28. AnonymousAuthenticationFilter
  29. OAuth2AuthorizationCodeGrantFilter
  30. SessionManagementFilter
  31. ExceptionTranslationFilter
  32. FilterSecurityInterceptor
  33. SwitchUserFilter

安全异常处理

首先,ExceptionTranslationFilter 调用 FilterChain.doFilter(request, response) 来调用应用程序的其余部分。

如果用户未通过身份验证或者是 AuthenticationException,则开始身份验证。

SecurityContextHolder 被清除
HttpServletRequest 保存在 RequestCache 中。 当用户成功认证后,RequestCache 用于重放原始请求。
AuthenticationEntryPoint 用于从客户端请求凭据。 例如,它可能重定向到登录页面或发送 WWW-Authenticate 标头。

否则,如果是 AccessDeniedException,则拒绝访问。 调用 AccessDeniedHandler 来处理拒绝访问。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值