iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >springSecurity之AuthenticationProvider用法解析
  • 369
分享到

springSecurity之AuthenticationProvider用法解析

Python 官方文档:入门教程 => 点击学习

摘要

目录AuthenticationProvider解析从源码中可以看到总结AuthenticationProvider解析 首先进入到AuthenticationProvider源码中

AuthenticationProvider解析

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

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

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

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

在这里插入图片描述

当我们没有指定相关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对认证请求链进行管理。

在这里插入图片描述

从源码中可以看到

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;
	}

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。

--结束END--

本文标题: springSecurity之AuthenticationProvider用法解析

本文链接: https://www.lsjlt.com/news/200349.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作