温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

springSecurity之AuthenticationProvider怎么使用

发布时间:2023-03-17 16:49:03 来源:亿速云 阅读:122 作者:iii 栏目:开发技术

本文小编为大家详细介绍“springSecurity之AuthenticationProvider怎么使用”,内容详细,步骤清晰,细节处理妥当,希望这篇“springSecurity之AuthenticationProvider怎么使用”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。

AuthenticationProvider解析

首先进入到AuthenticationProvider源码中可以看到它只是个简单的接口里面也只有两个方法:

public interface AuthenticationProvider {
	// 具体认证流程
	Authentication authenticate(Authentication authentication)
			throws AuthenticationException;	
    // supports函数用来指明该Provider是否适用于该类型的认证,如果不合适,则寻找另一个Provider进行验证处理。	
	boolean supports(Class<?> authentication);
}

AuthenticationProvider是用户自定义身份认证,认证流程顶级接口。

唯一作用即使用来进行身份验证,同时springSecurity也为我们提供了很多方便的实现类。

springSecurity之AuthenticationProvider怎么使用

当我们没有指定相关AuthenticationProvider 对象时springSecurity默认使用的就时上图中的DaoAuthenticationProvider进行验证。

也就是最常见的账户名密码的方式。但是实际开发中我们往往需要实现自定义认证流程比如最常见的短信验证码,第三方登录等等。

这个时候我们就可以通过实现自己的 AuthenticationProvider方式来进行自定义认证。

只需要在WebSecurityConfigurerAdapter适配器类的config方法中加入自己实现的AuthenticationProvider 即可。

 @Override
    protected void configure(AuthenticationManagerBuilder auth) {
        auth.authenticationProvider(authenticationProvider());
    }

说到AuthenticationProvider就离不开AuthenticationManager这个接口

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

同样的AuthenticationManager也是一个顶级接口,可以看到它其中也定义了一个跟AuthenticationProvider一摸一样的方法。

如果说Auth ntic ationProvider是对认证的具体实现,则AuthenticationManager则是对我们众多AuthenticationProvider的一个统一管理。

Authentication Ma nager的实现有很多,通常使用ProviderManager对认证请求链进行管理。

springSecurity之AuthenticationProvider怎么使用

从源码中可以看到

ProviderManager提供了一个list对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();

		for (AuthenticationProvider provider : getProviders()) {
			// 如果支持认证实现类就继续处理
			if (!provider.supports(toTest)) {
				continue;
			}

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

			try {
			  // 调用实现类的authenticate方法进行真实业务逻辑认证处理
				result = provider.authenticate(authentication);

				if (result != null) {
					copyDetails(authentication, result);
					break;
				}
			}
			catch (AccountStatusException e) {
				prepareException(e, authentication);
				// SEC-546: Avoid polling additional providers if auth failure is due to
				// invalid account status
				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 {
				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)) {
				// Authentication is complete. Remove credentials and other secret data
				// from authentication
				((CredentialsContainer) result).eraseCredentials();
			}

			// If the parent AuthenticationManager was attempted and successful than it will publish an AuthenticationSuccessEvent
			// This check prevents a duplicate AuthenticationSuccessEvent if the parent AuthenticationManager already published it
			if (parentResult == null) {
			  //  //发送认证成功事件
				eventPublisher.publishAuthenticationSuccess(result);
			}
			return result;
		}

		// Parent was null, or didn't authenticate (or throw an exception).

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

		// If the parent AuthenticationManager was attempted and failed than it will publish an AbstractAuthenticationFailureEvent
		// This check prevents a duplicate AbstractAuthenticationFailureEvent if the parent AuthenticationManager already published it
		if (parentException == null) {
			prepareException(lastException, authentication);
		}

		throw lastException;
	}

读到这里,这篇“springSecurity之AuthenticationProvider怎么使用”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注亿速云行业资讯频道。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI