【问题标题】:Spring Security multiple successful authentication providersSpring Security 多个成功的身份验证提供程序
【发布时间】:2018-05-07 18:52:04
【问题描述】:

我希望我的 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 行为。有什么建议吗?

【问题讨论】:

  • 这怎么可能?如果您的身份验证提供程序公开身份验证,为什么要 LDAP 进行身份验证,您已经通过身份验证。唯一的方法是,您的身份验证提供程序不会公开身份验证。所以你还没有通过身份验证。

标签: spring authentication spring-security kotlin


【解决方案1】:

也许我有一些。但是让我们分析一下之前的幕后情况。

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

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

在源代码中是这样的(为简洁起见,细节略过):

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. 确保您的自定义身份验证提供程序处理所有必要的身份验证操作。

【讨论】:

  • 老兄!看java if (result != null) { // ... ... break; } 你已经猜到了!成功返回null,它会处理下一个!异常会破坏 for 循环。所以,为下一个返回 null,为拒绝而抛出!
猜你喜欢
  • 2012-02-18
  • 2012-03-07
  • 2016-05-23
  • 2019-08-08
  • 1970-01-01
  • 2012-01-15
  • 1970-01-01
  • 2018-05-21
  • 2013-04-25
相关资源
最近更新 更多