springSecurity---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;
	}
  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Spring Security 可以通过使用 JWT(JSON Web Token)来实现身份验证和授权。要整合 Spring Security 与 JWT,可以使用 Spring Security 提供的模块Spring Security JWT,并编写相应的代码实现。 ### 回答2: springsecurity整合jwt的代码,主要包含以下几个方面的实现: 1. 导入相关依赖: 在Maven项目中,需要在pom.xml文件中添加相应的依赖,包括spring-security-core、spring-security-web、spring-security-config、jjwt等。 2. 创建JwtTokenUtil类: 定义一个JwtTokenUtil类,该类负责生成和解析JWT令牌,并提供一些辅助方法。其中,生成JWT令牌的方法需要使用jjwt库。 3. 创建JwtAuthenticationToken类: 自定义一个JwtAuthenticationToken类,继承自UsernamePasswordAuthenticationToken,用于存储从JWT令牌中解析出的用户信息。 4. 创建JwtAuthenticationFilter类: 自定义一个JwtAuthenticationFilter类,继承自OncePerRequestFilter,用于拦截请求,并对JWT进行验证和解析。 5. 创建JwtAuthenticationProvider类: 自定义一个JwtAuthenticationProvider类,实现AuthenticationProvider接口,用于验证从JWT中解析出的用户信息。 6. 配置Spring Security: 在Spring Security的配置类中,通过继承WebSecurityConfigurerAdapter类,并重写configure方法来配置Spring Security的一些行为。其中,需要自定义的是configure方法,配置过程中需要配置JwtAuthenticationFilter和JwtAuthenticationProvider。同时,还需要配置用户登录验证的方式以及权限控制规则。 7. 创建登录认证请求的接口: 创建登录认证请求的接口,该接口负责验证用户账号密码,并生成JWT令牌返回给用户。 以上是springsecurity整合jwt的代码实现步骤,其中包含了相关的类和依赖的设置。具体的代码实现细节可以根据具体需求进行相应修改和完善。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值