0
点赞
收藏
分享

微信扫一扫

Spring Security Authentication(一):架构组件

本文介绍 Spring Security 在 Servlet 认证中使用的主要架构组件。


目录

  • SecurityContextHolder
    • 设置身份认证信息
    • 访问当前已通过身份认证的用户信息
  • SecurityContext
  • Authentication
  • GrantedAuthority
  • AuthenticationManager
  • ProviderManager
  • AuthenticationProvider
  • 带有 AuthenticationEntryPoint 的请求凭证
  • AbstractAuthenticationProcessingFilter

SecurityContextHolder

SecurityContextHolder 是 Spring Security 身份认证模型的核心,包含 SecurityContext
SecurityContextHolder 用于存储 Spring Security 已通过身份认证的用户详情。
Spring Security 并不关心如何填充 SecurityContextHolder,如果它包含一个值,那么它将用作当前经过身份验证的用户。

设置身份认证信息

指示用户已通过身份验证的最简单方法是直接设置 SecurityContextHolder

SecurityContext context = SecurityContextHolder.createEmptyContext(); 
Authentication authentication = new TestingAuthenticationToken("username", "password", "ROLE_USER"); 
context.setAuthentication(authentication);
SecurityContextHolder.setContext(context); 

说明:

  1. 创建一个空的 SecurityContext 对象。注意:如果直接调用 SecurityContextHolder.getContext().setAuthentication(authentication) 不能避免多线程竞争;
  2. 创建一个 Authentication 对象。Spring Security 并不关心设置给 SecurityContextAuthentication 对象的具体实现,这里使用 TestingAuthenticationToken 是因为方便使用。生产环境中最常用的应该是 UsernamePasswordAuthenticationToken(userDetails, password, authorities)
  3. SecurityContext 设置给 SecurityContextHolder,Spring Security 将使用这些信息进行授权。
访问当前已通过身份认证的用户信息
SecurityContext context = SecurityContextHolder.getContext();
Authentication authentication = context.getAuthentication();
String username = authentication.getName();
Object principal = authentication.getPrincipal();
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();

默认情况下 SecurityContextHolder 使用 ThreadLocal 存储这些详情,这意味着 SecurityContext 始终可用于同一执行线程中的方法,即使没有将 SecurityContext 作为这些方法的参数显式传递。可以在启动时配置 SecurityContextHolder 以指定如何存储上下文。


SecurityContext

SecurityContextHolder 获取,包含当前通过身份认证(Authenticated)的用户的 Authentication 对象。


Authentication

Authentication 在 Spring Security 中有两个主要用途:

  • 作为 AuthenticationManager 的输入提供用户提交的用于身份认证的凭据。在此场景下使用时 isAuthenticated() 方法返回 false
  • 代表当前已通过身份认证的用户,可以从 SecurityContext 中获取当前的 Authentication 对象。

Authentication 对象 包含:

  • principal:用于识别用户身份,如果使用用户名/密码方式执行的认证,这通常是一个 UserDetails 实例。
  • credentials:通常是密码,在很多情况下,一旦用户通过身份认证,这部分内容便会被清除以确保不会泄露。
  • authoritiesGrantedAuthority 集合,是用户被授予的更高级别权限,如角色和范围。

GrantedAuthority

GrantedAuthority 是用户被授予的更高级别权限,如角色和范围。
GrantedAuthority 集合可以通过 Authentication.getAuthorities() 获取。


AuthenticationManager

定义 Spring Security 过滤器如何执行身份认证的 API。认证通过后返回的 Authentication 对象由调用 AuthenticationManager 的控制器(Controller)设置到 SecurityContextHolder 中。

如果不使用 Spring Security 过滤器,可以直接设置 SecurityContextHolder,并不需要使用 AuthenticationManager


ProviderManager

ProviderManagerAuthenticationManager 最常用的实现。ProviderManager 将认证委托给一个 AuthenticationProvider 列表,每个 AuthenticationProvider 都有机会指明认证结果是成功还是失败,又或无法做出认证结果决定并允许下游的 AuthenticationProvider 来做此决定。

如果所有已配置的 AuthenticationProvider 都无法做出认证结果决定,则认证结果即为失败并抛出一个 ProviderNotFoundException 异常。ProviderNotFoundException 异常继承自 AuthenticationException,说明 ProviderManager 未配置支持此类型身份认证。


AuthenticationProvider

ProviderManager 用于执行特定类型的身份认证。ProviderManager 中可以注入多个 AuthenticationProvider,每个 AuthenticationProvider 执行一种特定类型的身份认证,例如:

  • DaoAuthenticationProvider:支持基于用户名/密码的基础认证;
  • JwtAuthenticationProvider:支持认证 JWT Token。

带有 AuthenticationEntryPoint 的请求凭证

AuthenticationEntryPoint 用于发送 HTTP 响应,此响应包含了请求客户端认证凭证。有时客户端在请求资源时会主动带上认证凭证,在这些情况下 Spring Security 是不需要发送 HTTP 响应要求客户端发送认证凭证,因为已经在之前的请求中带上了。但在另一些情况下,客户端在尚未认证时请求了一些未授权的资源,此时需要发送一个 AuthenticationEntryPoint 实现要求客户端发回认证凭证。


AbstractAuthenticationProcessingFilter

AbstractAuthenticationProcessingFilter 是执行用户身份认证的最基础的过滤器。
AbstractAuthenticationProcessingFilter 执行认证的流程:

  1. 用户提交了认证凭证后,AbstractAuthenticationProcessingFilter 从要认证的 HttpServletRequest 中创建了一个 Authentication 对象,创建的 Authentication 对象的类型取决于 AbstractAuthenticationProcessingFilter 的子类。例如,UsernamePasswordAuthenticationFilterHttpServletRequest 中解析出 usernamepassword,并据此创建 UsernamePasswordAuthenticationToken
  2. Authentication 对象被传递给 AuthenticationManager 进行身份认证;
  3. 如果认证失败将执行以下操作:
    • SecurityContextHolder 被清空。
    • RememberMeServices.loginFail 被调用,如果未配置 Remember Me 则不处理。
    • AuthenticationFailureHandler 被调用。
  4. 如果认证成功则执行以下操作:
    • 通知 SessionAuthenticationStrategy 有一个新的登录。
    • Authentication 被设置到 SecurityContextHolder 中,之后 SecurityContextPersistenceFilterSecurityContext 保存到 HttpSession 中。
    • RememberMeServices.loginSuccess 被调用,如果未配置 Remember Me 则不处理
    • ApplicationEventPublisher 发布一个 InteractiveAuthenticationSuccessEvent 事件。
举报

相关推荐

0 条评论