ITPub博客

首页 > 数据库 > 数据库开发技术 > SpringSecurity 整体认证流程

SpringSecurity 整体认证流程

原创 数据库开发技术 作者:DevXTalk 时间:2024-01-01 09:30:00 0 删除 编辑

SpringSecurity整体认证流程

认证配置流程

  • HttpSecurityConfiguration
  • WebSecurityConfiguration
  • DelegatingFilterProxy

HttpSecurityConfiguration创建了HttpSecurity ——> HttpSecurity会构建DefaultSecurityFilterChain

WebSecurityConfiguration会将DefaultSecurityFilterChain注入到securityFilterChains属性中。并将DefaultSecurityFilterChain添加到WebSecurity中,最终由 WebSecurity 构建出 FilterChainProxy 来执行SpringSecurity 的过滤逻辑。

DelegatingFilterProxy是springWeb中的类,有一个delegate属性其值为FilterChainProxy对象。「DelegatingFilterProxy是真正会注册到Tomcat容器中的Filter」

认证流程

  • Authentication
  • AuthenticationProvider
  • ProviderManager
  • AuthenticationManager
  • AuthenticationManagerBuilder
  1. 使用AuthenticationManagerBuilder来构建AuthenticationManager(实现类为ProviderManager)。
  2. 在ProviderManager中维护了AuthenticationProvider集合和一个类型为ProviderManager的父类属性。认证时先使用自身的ProviderManager认证,自身若不支持再使用父类的ProviderManager认证。
  3. AuthenticationProvider就是真正做认证的类,传递的认证对象则为Authentication。如果支持传入的Authentication认证对象,则会调用authenticate进行认证。

Authentication 代表请求认证的token,或通过AuthenticationManager.authenticate(Authentication)认证过的主体对象

public interface Authentication extends Principal, Serializable {

Collection<? extends GrantedAuthority> getAuthorities();
// 登录凭证
Object getCredentials();

Object getDetails();

Object getPrincipal();

boolean isAuthenticated();

void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException;

}

AuthenticationProvider:做认证和授权的。策略模式非常适合一个问题有多种解决方案的场景。对扩展开放解耦。比如一个用户有多种登录方式,用户名密码、手机号验证码、微信登录等等。

public interface AuthenticationProvider {

Authentication authenticate(Authentication authentication) throws AuthenticationException;


boolean supports(Class<?> authentication);

}

ProviderManager:实现了AuthenticationManager,持有所有认证策略(AuthenticationProvider)。并且还有一个父类属性ProviderManager。

认证流程:先使用自己持有的AuthenticationProvider进行认证,如果没有认证成功再使用父类的ProviderManager进行认证。

ProviderManager的核心方法就是authenticate方法。

public class ProviderManager implements AuthenticationManager, MessageSourceAware, InitializingBean {

private List<AuthenticationProvider> providers = Collections.emptyList();

protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();

private AuthenticationManager parent;

// 是否擦除认证信息,认证成功后擦除凭证(密码)
private boolean eraseCredentialsAfterAuthentication = true;


@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
// 使用自身的AuthenticationProvider进行认证
for (AuthenticationProvider provider : getProviders()) {
if (!provider.supports(toTest)) {
continue;
}
result = provider.authenticate(authentication);
}
// 未认证,使用父认证AuthenticationProvider进行认证
if (result == null && this.parent != null) {
parentResult = this.parent.authenticate(authentication);
result = parentResult;
}
if (result != null) {
// 认证成功后,擦除认证信息(密码)
if (this.eraseCredentialsAfterAuthentication && (result instanceof CredentialsContainer)) {
if (parentResult == null) {
this.eventPublisher.publishAuthenticationSuccess(result);
}

return result;
}

// parent是空,并且也没有认证处理器处理就抛出异常
if (lastException == null) {
lastException = new ProviderNotFoundException(this.messages.getMessage("ProviderManager.providerNotFound",
new Object[] { toTest.getName() }, "No AuthenticationProvider found for {0}"));
}
// 处理异常
if (parentException == null) {
prepareException(lastException, authentication);
}
throw lastException;
}
}

AuthenticationManager:处理认证Authentication请求。重要的实现类为AuthenticationProvider。

// Processes an Authentication request.
public interface AuthenticationManager {

/**
* 尝试通过 Authentication 对象做认证。
* 返回已经认证的(填充了认证信息和授权信息)的Authentication
*/

Authentication authenticate(Authentication authentication) throws AuthenticationException;

}

AuthenticationManagerBuilder:是SecurityBuilder的子类用于构建AuthenticationManager。performBuild方法构建的就是一个ProviderManager对象,构造器中传入了authenticationProviders和parentAuthenticationManager来

public class AuthenticationManagerBuilder
extends AbstractConfiguredSecurityBuilder<AuthenticationManager, AuthenticationManagerBuilder>
implements ProviderManagerBuilder<AuthenticationManagerBuilder>
{


@Override
protected ProviderManager performBuild() throws Exception {
// 直接new来创建ProviderManager,传入了authenticationProviders和父parentAuthenticationManager
ProviderManager providerManager = new ProviderManager(this.authenticationProviders, this.parentAuthenticationManager);
if (this.eraseCredentials != null) {
providerManager.setEraseCredentialsAfterAuthentication(this.eraseCredentials);
}
if (this.eventPublisher != null) {
providerManager.setAuthenticationEventPublisher(this.eventPublisher);
}
// 安全对象的后处理,对安全对象的扩展
providerManager = postProcess(providerManager);
return providerManager;
}


}


欢迎加入 DevXTalk 的技术交流群,在这里你可以和大佬们一起交流分享技术,行业经验,提升自我。结识新的业内朋友,扩大自己的圈子,当你想换工作的时候也许就能拿到不错的 offer 。总之期待你的加入...


「看完本文有收获?转发给更多的朋友吧」

「DevXTalk 不止于技术」

原文作者:DevXTalk;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论

注册时间:2019-03-23

  • 博文量
    178
  • 访问量
    82575