任何安全框架的核心目标之一是验证调用者的声明,调用者就是他们声称的身份。身份验证是验证凭据和调用者声明的过程。在这篇文章中,我们将了解Spring Security认证架构的核心及其各个组件。
让我们看一下安全身份验证过程中涉及的类和过滤器的顶级工作流程。
Spring Security附带了一组安全过滤器。对服务器的每个请求都会被这些过滤器拦截。这些过滤器将根据逻辑处理请求,并通过或拒绝传入的请求,让我们看看身份验证过程的不同步骤。
每个传入请求都将经过一系列过滤器以进行身份验证和授权过程。看上图中的步骤1,每个请求都经过安全过滤器链。请记住以下几点。
每个请求都会通过过滤器,直到到达相关的身份验证过滤器。
每个请求都可以通过一组不同的安全过滤器。我们可以通过请求模式甚至基于请求标头来配置过滤器。
在上图中,登录请求经过过滤器链并到达UsernamePasswordAuthenticationFilter.
类似地,基本身份验证请求会经过过滤器链,直到到达BasicAuthenticationFilter。
对于用户登录,一旦身份验证请求到达身份验证过滤器,它将从请求负载中提取用户名和密码。Spring security 将根据用户名和密码创建一个 Authentication 对象。这是身份验证对象创建的样子:
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(username, password);
身份验证管理器是Spring 安全身份验证过程的核心。是定义Spring Security 的 FiltersAuthenticationManager如何执行身份验证的 API 。
public interface AuthenticationManager { Authentication authenticate(Authentication authentication) throwsAuthenticationException;}
在我们继续之前,让我们先介绍一下 AuthenticationManager 的要点。
在内部,他们AuthenticationProvider 负责执行身份验证过程。
ProviderManagermanager 是最常用的实现AuthenticationProvider.
ProviderManager将请求委托给列表AuthenticationProvider(我们将在本系列中详细讨论这一点)。
它们AuthenticationProvider负责处理请求并执行特定的身份验证。它提供了一种获取用户详细信息的机制,我们可以用它来执行身份验证。界面如下所示AuthenticationProvider:
public interface AuthenticationProvider { Authentication authenticate(Authentication authentication) throws AuthenticationException; boolean supports(Class<?> authentication); }
我们AuthenticationProvider不能直接执行,但我们可以使用AuthenticationProvider.
如果您好奇,这里是一些 OOTB 身份验证提供商的列表。
DaoAuthenticationProvider。
JAAS认证
开放身份验证
X509认证
SAML 2.0
OAuth 2.0
记住我身份验证提供者
Ldap身份验证提供者
对于企业应用程序,我们可能需要一个自定义的身份验证提供程序。实现AuthenticationProvider接口来为您的应用程序创建自定义身份验证提供程序。
@Component public class CustomAuthenticationProvider implements AuthenticationProvider { @Override public Authentication authenticate(Authentication auth) throws AuthenticationException { String username = authentication.getName(); String pwd = authentication.getCredentials().toString(); if ("javadevjournal".equals(username) && "pass".equals(pwd)) { return new UsernamePasswordAuthenticationToken(username, password, Collections.emptyList()); } else { throw new BadCredentialsException("User authentication failed!!!!"); } } @Override public boolean supports(Class<?>auth) { return auth.equals(UsernamePasswordAuthenticationToken.class); } }
最后一步是使用 Spring security 配置我们的自定义身份验证提供程序。我们通过创建自定义配置类并扩展WebSecurityConfigurerAdapter.
@Configuration public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired CustomAuthenticationProvider customAuthenticationProvider; @Override public void configure(AuthenticationManagerBuilder auth) throws Exception { //configuring our custom auth provider auth.authenticationProvider(customAuthProvider); } }
并非全部(但很少有)身份验证提供程序可能需要UserDetailsService通过用户名(例如 )获取存储在数据库中的用户详细信息DaoAuthenticationProvider。大多数标准 Web 应用程序可能会UserDetailsService在登录过程中使用 来获取用户信息。界面如下UserDetailsService所示:
package org.springframework.security.core.userdetails; public interface UserDetailsService { UserDetails loadUserByUsername(String var1) throws UsernameNotFoundException; }
为我们的应用程序定义自定义 UserDetailsService是一个常见的用例。
在身份验证过程中,如果用户身份验证成功,我们将发送回一个完全初始化的 Authentication 对象。对于失败的身份验证,AuthenticationException将被抛出。完全填充的身份验证对象包含以下详细信息:
用户凭据。
授予权限列表(用于授权)。
认证标志。
public interface Authentication extends Principal, Serializable { Collection<? extends GrantedAuthority> getAuthorities(); Object getCredentials(); Object getDetails(); Object getPrincipal(); boolean isAuthenticated(); void setAuthenticated(boolean var1) throws IllegalArgumentException; }
成功身份验证的最后一步是在SecurityContext. 它包裹SecurityContext着SecurityContextHolder. 请记住以下几点:
这SecurityContextHolder是 Spring Security 存储有关经过身份验证的用户的详细信息的位置。
Spring security 不会验证如何 SecurityContextHolder填充。
如果它在 中找到值 SecurityContextHolder,则假定当前用户是经过身份验证的用户。
SecurityContextHolder这就是填充的方式
SecurityContext context = //get the context from security holder UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(username, password); context.setAuthentication(authentication); SecurityContextHolder.setContext(context);
在这篇文章中,我们看到了Spring Security的架构 和认证流程。我们还详细了解了spring security 的身份验证架构。总而言之,我们涵盖了以下内容。本文的源代码可在GitHub上获取。
spring security认证的整体架构是怎样的?
身份验证过滤器如何协同工作。
身份验证管理器的目的是什么?
身份验证提供商概述。
重要的是SecurityContextHolder