Spring Security多个成功的身份验证提供程

时间:2017-11-23 18:40:02

标签: spring authentication spring-security kotlin

我希望我的Web应用程序的用户可以通过LDAP和其他自定义身份验证进行身份验证。它是用Kotlin编写的Spring Boot应用程序。我已将AuthenticationManagerBuilder配置如下

@Autowired
lateinit var authenticationProvider: CustomAuthenticationProvider

override fun configure(auth: AuthenticationManagerBuilder) {
    auth
            .authenticationProvider(authenticationProvider)

    auth
            .ldapAuthentication()
                .userDnPatterns("uid={0},ou=people")
                .groupSearchBase("ou=groups")
                .contextSource()
                .url("ldap://localhost:8389/dc=example,dc=com")
            .and()
                .passwordCompare()
                .passwordEncoder(PlaintextPasswordEncoder())
                .passwordAttribute("userPassword")
}

我想链接身份验证,以便在CustomAuthenticationProvider成功进行身份验证(函数身份验证不抛出)时,使用LDAP身份验证提供程序继续进行身份验证。

如果CustomAuthenticationProvider成功通过身份验证,则不会评估LDAP身份验证(以及任何后续身份验证提供程序)。仅当CustomAuthenticationProvider抛出时才执行LDAP身份验证。

我已阅读了许多文章(例如Multiple Authentication Providers in Spring Security),其中详细介绍了多个身份验证提供程序但具有OR行为而非AND行为。有什么建议吗?

1 个答案:

答案 0 :(得分:0)

也许我有一些。但是,让我们分析之前发生的事情。

Spring Security中的默认身份验证管理器实现(ProviderManager)维护一个身份验证提供程序列表,第一个执行成功身份验证的实现程序会停止链 - 其余的不会被调用。我确定你无法改变它。当您使用AuthenticationManagerBuilder时,可以在ProviderManager

中添加身份验证提供程序

下图中显示了正在发生的事情的高级概述:

Security architecture

在源代码中,这看起来像这样(为简洁起见,跳过了详细信息):

public Authentication authenticate(Authentication authentication)
            throws AuthenticationException {
        Class<? extends Authentication> toTest = authentication.getClass();
        ...
        for (AuthenticationProvider provider : getProviders()) {
            if (!provider.supports(toTest)) {
                continue;
            }

            try {
                result = provider.authenticate(authentication);

                if (result != null) {
          ...
                    break;
                }
            }
      ...
            catch (AuthenticationException e) {
                lastException = e;
            }
        }

        if (result != null) {
            ...
            return result;
        }
  }

那你能做什么......嗯。首先@dur的问题是有效的:-)第二 - 显然你不能用标准的认证管理器做你想做的事情。这对我来说很有意义。

我认为如果你仍然想要这样做,你可以尝试两件事:

  1. 在过滤器链中提供您自己的身份验证管理器实现。这对我来说似乎有点挑战。
  2. 确保您的自定义身份验证提供程序处理所有必要的身份验证操作。