Spring Security 认证过程几个重要对象

Spring Security 认证过程几个重要对象,第1张

关于
  1. spring security 官网链接, 本次示例使用的版本为5.6.3:https://docs.spring.io/spring-security/reference/index.html
  2. 什么是认证:通俗点点理解来理解就是登录。随着互联网的发展,登录的方式也变得五花八门。较为常见的有账号密码登录,手机号验证码登录,三方登录等多种形式。
1. SpringSecurity中谁负责认证呢? AuthenticationProvider

事实上,上面的问题是不固定。用户可以通过很多组件来实现用户的认证。如通过Filter (Interceptor也类似)通过获取请求中传递的认证参数来做认证,或通过Controller中的接口来直接认证。

AuthenticationProvider 实际上是一个接口,具体实现要用户根据自身的需求来进行定制。

通过查看源代码很容易了解对应方法的逻辑。 一个是负责认证的业务逻辑。一个是决定当前 Provider是否可以对用户传递的认证主体进行认证。

package org.springframework.security.authentication;

import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;

public interface AuthenticationProvider {
	/**
	*	authentication: 认证的主体,开发者需要将需要认证的数据封装其中
	*	@return 认证通过后,将真实的用户信息进行封装返回
	**/
    Authentication authenticate(Authentication authentication) throws AuthenticationException;
	
	/*
	* 判断当前的authentication类型 本AuthenticationProvider是否可以处理
	* */
    boolean supports(Class<?> authentication);
}
2. 认证所需要的数据主体 Authentication


通过查看 Authentication 接口的源码发现很难看出一个所以然。所以我们可以通过其已有的实现类来查看其每个方法的用途。以及我们如何去进行自定义和拓展。

2.1 最熟悉以及经典的的实现 UsernamePasswordAuthenticationToken

如果你需要自定义认证主体,那么可以模仿 UsernamePasswordAuthenticationToken的实现,同时要注意我圈出来的位置。

首先,需要理解,为什么需要这样设计两个构造函数?

这和上面聊到的 AuthenticationProvider 中 authenticate 方法的 参数 和 返回值是对应的:

  1. 参数: 待认证的主体,调用的是第一个构造方法。
  2. 返回值: 认证完成后重新构造的主体,调用的是第二个构造方法。 通过注释也能看到,这个方法一般是在AuthenticationProvider中进行调用。

我们针对源码对几个重要对象进行分析:

/**
 * An {@link org.springframework.security.core.Authentication} implementation that is
 * designed for simple presentation of a username and password.
 * 

* The principal and credentials should be set with an * Object that provides the respective property via its * Object.toString() method. The simplest such Object to use is * String. * * @author Ben Alex */ public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationToken { private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; private final Object principal; private Object credentials; /** * This constructor can be safely used by any code that wishes to create a * UsernamePasswordAuthenticationToken, as the {@link #isAuthenticated()} * will return false. * */ public UsernamePasswordAuthenticationToken(Object principal, Object credentials) { super(null); this.principal = principal; this.credentials = credentials; setAuthenticated(false); } /** * 这个构造器应该只能被 AuthenticationManager 或者 AuthenticationProvider 的实现来使用,创建一个 * 被认证的对象。 * * This constructor should only be used by AuthenticationManager or * AuthenticationProvider implementations that are satisfied with * producing a trusted (i.e. {@link #isAuthenticated()} = true) * authentication token. * @param principal * @param credentials * @param authorities */ public UsernamePasswordAuthenticationToken(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities) { super(authorities); this.principal = principal; this.credentials = credentials; super.setAuthenticated(true); // must use super, as we override } @Override public Object getCredentials() { return this.credentials; } @Override public Object getPrincipal() { return this.principal; } @Override public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException { Assert.isTrue(!isAuthenticated, "Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead"); super.setAuthenticated(false); } @Override public void eraseCredentials() { super.eraseCredentials(); this.credentials = null; } }

3 Authentication(未认证) 的构造时机 (过滤器)

首先我们来分析一下UsernamePasswordAuthenticationFilter 的实现逻辑:

其中本类中的核心逻辑都在attemptAuthentication方法中,下面我们可以仔细分析一下这个方法的具体流程。

在此处,我们立马就明白了,在未认证前, UsernamePasswordAuthenticationToken 中的两个属性分别代表:

	// 用户名 
	private final Object principal;
	// 密码
	private Object credentials;

同时发现,按照我们前面的描述,认证的具体逻辑应该是由AuthenticationProvider 来来实现的,但此处为什么是AuthenticationManager 呢?

Spring Security 为了实现多种认证方式并存,于是抽象出一个 AuthenticationManager, 用来管理多个 AuthenticationProvider,每一个 AuthenticationProvider负责一种认证方式

下面我们就以Spring Security中默认的AuthenticationManager实现:ProviderManager 来看一下具体实现机制。

完全可以看出,其中认证的具体逻辑还是AuthenticationProvider进行实现。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/730455.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-27
下一篇 2022-04-27

发表评论

登录后才能评论

评论列表(0条)

保存