spring security源码核心类分析

AuthenticationManager----认证接口,该对象提供了认证入口,接收一个Authentication对象作为参数Authentication对象本身也是一个接口,提供了获取认证用户的用户名、密码、用户详情、认证状态等方法。

 分析Authentication对象时我们主要关注常用的下面两个类RememberMeAuthenticationToken,UsernamePasswordAuthenticationToken

ProviderManager----AuthenticationManager接口的实现类,实现了基本的认证逻辑并扩展了一些功能,其中ProviderManager实现类的构造函数中使用List<AuthenticationProvider> providers作为入参,意义在于为认证引入更多不同形式的认证实现,通过AuthenticationProvider可以扩展认证方式。

 

//ProviderManager中的认证实现源码
public Authentication authenticate(Authentication authentication)
			throws AuthenticationException {
		Class<? extends Authentication> toTest = authentication.getClass();
		AuthenticationException lastException = null;
		AuthenticationException parentException = null;
		Authentication result = null;
		Authentication parentResult = null;
		boolean debug = logger.isDebugEnabled();

        //此处就用到了引入的认证实现,认证过程会先使用引入AuthenticationProvider的认证,如果引入的认证都没有认证成功则会使用原始的AuthenticationManager提供的认证
		for (AuthenticationProvider provider : getProviders()) {
			if (!provider.supports(toTest)) {
				continue;
			}

			if (debug) {
				logger.debug("Authentication attempt using "
						+ provider.getClass().getName());
			}

			try {
				result = provider.authenticate(authentication);

				if (result != null) {
					copyDetails(authentication, result);
					break;
				}
			}
			catch (AccountStatusException e) {
				prepareException(e, authentication);
				//如果身份验证失败是由于无效的帐户状态引起的,请避免轮询其他提供认证的程序
				throw e;
			}
			catch (InternalAuthenticationServiceException e) {
				prepareException(e, authentication);
				throw e;
			}
			catch (AuthenticationException e) {
				lastException = e;
			}
		}

		if (result == null && parent != null) {
			// Allow the parent to try.
			try {
                
                //引入的AuthenticationProvider都认证失败则使用原始的AuthenticationManager提供的认证
				result = parentResult = parent.authenticate(authentication);
			}
			catch (ProviderNotFoundException e) {
				// ignore as we will throw below if no other exception occurred prior to
				// calling parent and the parent
				// may throw ProviderNotFound even though a provider in the child already
				// handled the request
			}
			catch (AuthenticationException e) {
				lastException = parentException = e;
			}
		}

		if (result != null) {
			if (eraseCredentialsAfterAuthentication
					&& (result instanceof CredentialsContainer)) {
				// 认证完成。从身份验证中删除凭据和其他秘密数据
				((CredentialsContainer) result).eraseCredentials();
			}

			// 如果父 AuthenticationManager 已尝试并成功,那么它将发布一个 AuthenticationSuccessEvent 如果父 AuthenticationManager 已经发布了它,此检查可防止重复的 AuthenticationSuccessEvent
			if (parentResult == null) {
				eventPublisher.publishAuthenticationSuccess(result);
			}
			return result;
		}


		if (lastException == null) {
			lastException = new ProviderNotFoundException(messages.getMessage(
					"ProviderManager.providerNotFound",
					new Object[] { toTest.getName() },
					"No AuthenticationProvider found for {0}"));
		}

		// 如果父 AuthenticationManager 已尝试但失败,则它将发布 AbstractAuthenticationFailureEvent 如果父 AuthenticationManager 已发布,此检查可防止重复 AbstractAuthenticationFailureEvent
		if (parentException == null) {
			prepareException(lastException, authentication);
		}

		throw lastException;
	}

AuthenticationProvider----ProviderManager 通过 AuthenticationProvider 扩展出更多的验证提供的方式;而 AuthenticationProvider 本身也就是一个接口,从类图中我们可以看出它的实现类AbstractUserDetailsAuthenticationProvider和AbstractUserDetailsAuthenticationProvider的子类DaoAuthenticationProvider。DaoAuthenticationProvider是Spring Security中一个核心的Provider,对所有的数据库提供了基本方法和入口。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

龙茶清欢

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值