当前位置: 首页 > 知识库问答 >
问题:

在多域环境中向spring-security添加多个ldap源

易弘阔
2023-03-14

我正试图在一个分割域环境中为spring security添加一个辅助ldap contextSource,但我似乎没有完成。我知道以前也曾问过类似的问题,但这是针对登录到同一应用程序中的两个独立域的问题。

<beans:bean id="secondaryContextSource" class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
    <beans:constructor-arg value="ldap://<ldap address>:389/DC=example,DC=com"/>
    <beans:property name="userDn" value="CN=BindAccount,CN=Users,DC=example,DC=com" />
    <beans:property name="password" value="examplepw" />
</beans:bean>
    <beans:bean id="ldapAuthenticationProvider" class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">    
    <beans:constructor-arg>
        <beans:bean class="org.springframework.security.ldap.authentication.BindAuthenticator">
            <beans:constructor-arg ref="contextSource" />
            <beans:constructor-arg ref="secondaryContextSource" />
            <beans:property name="userSearch">
                <beans:bean id="userSearch" class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
                  <beans:constructor-arg index="0" value="CN=Users"/>
                  <beans:constructor-arg index="1" value="(userPrincipalName={0})"/>
                  <beans:constructor-arg index="2" ref="contextSource" />
                </beans:bean>
            </beans:property>

        </beans:bean>
    </beans:constructor-arg>       
     <beans:property name="userDetailsContextMapper">
        <beans:bean id="employeeServiceFacade" class="com.example.service.security.EmployeeServiceFacade" />
    </beans:property>   
      <beans:constructor-arg>
        <beans:bean class="com.example.web.security.CustomLdapAuthoritiesPopulator" />
    </beans:constructor-arg>
</beans:bean>
public class ExtendedBindAuthenticator extends AbstractLdapAuthenticator {

    private BaseLdapPathContextSource secondaryContextSource;

    public void setSecondContextSource(BaseLdapPathContextSource secondContextSource) {
        this.secondaryContextSource = secondaryContextSource;
    }


    public ExtendedBindAuthenticator(BaseLdapPathContextSource contextSource, BaseLdapPathContextSource secondContextSource) {
        super(contextSource);
        this.secondaryContextSource = secondaryContextSource;
    }


    public DirContextOperations authenticate(Authentication authentication) {
        DirContextOperations user = null;
        Assert.isInstanceOf(UsernamePasswordAuthenticationToken.class, authentication,
                "Can only process UsernamePasswordAuthenticationToken objects");

        String username = authentication.getName();
        String password = (String)authentication.getCredentials();         

        if(username.contains("secondDomain")) {
            DirContextOperations secondaryUser = getUserSearch().searchForUser(username);
            this.bindWithDn(secondaryUser.getDn().toString(), username, password);

        }


        if (!StringUtils.hasLength(password)) {

            throw new BadCredentialsException(messages.getMessage("BindAuthenticator.emptyPassword",
                    "Empty Password"));
        }

        // If DN patterns are configured, try authenticating with them directly
        for (String dn : getUserDns(username)) {
            user = this.bindWithDn(dn, username, password);

            if (user != null) {
                break;
            }
        }

        // Otherwise use the configured search object to find the user and authenticate with the returned DN.
        if (user == null && getUserSearch() != null) {
            DirContextOperations userFromSearch = getUserSearch().searchForUser(username);
            user = bindWithDn(userFromSearch.getDn().toString(), username, password);
        }

        if (user == null) {
            throw new BadCredentialsException(
                    messages.getMessage("BindAuthenticator.badCredentials", "Bad credentials"));
        }

        return user;
    }

    private DirContextOperations bindWithDn(String userDnStr, String username, String password) {
        BaseLdapPathContextSource ctxSource = (BaseLdapPathContextSource) getContextSource();

        if(username.contains("secondDomain")) {
            ctxSource = secondaryContextSource;
        }

        DistinguishedName userDn = new DistinguishedName(userDnStr);
        DistinguishedName fullDn = new DistinguishedName(userDn);
        fullDn.prepend(ctxSource.getBaseLdapPath());


        DirContext ctx = null;
        try {
            ctx = getContextSource().getContext(fullDn.toString(), password);
            // Check for password policy control
            PasswordPolicyControl ppolicy = PasswordPolicyControlExtractor.extractControl(ctx);



            Attributes attrs = ctx.getAttributes(userDn, getUserAttributes());

            DirContextAdapter result = new DirContextAdapter(attrs, userDn, ctxSource.getBaseLdapPath());

            if (ppolicy != null) {
                result.setAttributeValue(ppolicy.getID(), ppolicy);
            }

            return result;
        } catch (NamingException e) {
            // This will be thrown if an invalid user name is used and the method may
            // be called multiple times to try different names, so we trap the exception
            // unless a subclass wishes to implement more specialized behaviour.
            if ((e instanceof org.springframework.ldap.AuthenticationException)
                    || (e instanceof org.springframework.ldap.OperationNotSupportedException)) {
                handleBindException(userDnStr, username, e);
            } else {
                throw e;
            }
        } catch (javax.naming.NamingException e) {
            throw LdapUtils.convertLdapException(e);
        } finally {
            LdapUtils.closeContext(ctx);
        }

        return null;
    }

    /**
     * Allows subclasses to inspect the exception thrown by an attempt to bind with a particular DN.
     * The default implementation just reports the failure to the debug logger.
     */
    protected void handleBindException(String userDn, String username, Throwable cause) {
       System.out.println("Failed to bind as " + userDn + ": " + cause);
    }

}

如果任何人有任何经验与这类事情,我会非常感谢这一点,因为我找不到很多关于这一主题。我希望有人能告诉我,我是否在正确的轨道上,或者我是否应该以一种不同的方式去做这件事。为了澄清,我使用的是spring-security-ldap,而不是spring-ldap。还只是想提到,我确实有我的所有依赖在我的pom文件。谢谢!

共有1个答案

凌声
2023-03-14

从您的问题中并不完全清楚实际出了什么问题--例如,您的配置实际上不会加载,因为它使用了Spring Security的bindauthenticator并试图向它传递两个ContextSource参数。

如果我是您,我会避免尝试黑内部实现类,而是让它们单独运行,并根据您的选择标准编写一个单独的委派类。

首先,我将定义两个单独的ldapaAuthenticationProviderbean,每个域对应一个bean,首先确保您可以通过在单元测试中直接调用它们来对每个用户进行身份验证。在尝试将两者一起使用之前,请确保您可以为各自的域正确配置它们。

之后,我将它们连接到一个单独的委托authenticationprovider中。类似于:

public class DelegatingLdapAuthenticationProvider implements AuthenticationProvider {
    // Inject these via the app context
    private LdapAuthenticationProvider primary;
    private LdapAuthenticationProvider secondary;

    public Authentication authenticate(Authentication a) {
        if (a.getName().contains("secondDomain")) {
            return secondary.authenticate(a);
        } else {
            return primary.authenticate(a);
        }
    }
}

然后,我将这个bean配置为Spring Security实际调用的身份验证提供程序。

 类似资料:
  • 我有一个基于xml的Apache Shiro SecurityManager和几个自定义领域(它们扩展了领域中的构建)。我正在尝试迁移到Spring Boot,它主要是基于注释的。 目前,我可以通过创建一个ShiroConfig.java(由@Configuration注释),在ShiroConfig中手动创建每个领域的对象并将其添加到DefaultWebSecurityManager.SetRe

  • 我有一个java进程,我试图从bash文件中的环境变量加载多个参数。示例: 有办法解决这个问题吗?这是格式问题吗?这背后的想法是,如果我想使用一些其他/新参数,我不想更改脚本,我只想更改环境变量。 如果我把所有的东西都放在一行中,也许它会起作用,但是这会使实际的命令变得非常长,所以这不是一个最佳解决方案。 同样的事情也适用于一个属性。 我真的很欣赏其他方法。

  • 我们有一个应用程序正在使用。我试图将其更改为较新的版本。如果我没有指定或者如果我指定了一个作用域,那么应用程序可以正常工作。我在请求多个作用域(如)时遇到一个问题,该作用域在以前的版本中适用。 我请求的客户端具有所有权限。 当我使用时,为了获得一个令牌,我经常执行get调用,如 如果我用或来尝试它,它工作得很好,因为或是客户端作用域的一部分。 如果我想在中请求多个作用域,我该怎么做?

  • 我是Spring Boot的新手,所以如果我忽略了一些简单的东西,请原谅我。 使用Spring配置服务器,您可以指定via。yml文件您希望使用哪种类型的环境存储库(native、Git等)。这些环境存储库包含在第三方依赖项中。我想知道是否可以添加您自己的环境存储库,以便您可以连接到数据库以获取配置? 非常感谢!

  • 我正在尝试在我的列表中显示在EditText中收集的3个数据。在执行按钮时。如果有3个字段要添加,它们将单独存储给我。我可以在我的代码中做些什么来使其统一为列表中的单个字段?示例:姓名:薛西斯年龄:14描述罪行:当我离开学校时,他朝我吐口水。 当您点击保存按钮时: 你所期待的Jorge 14当我离开学校时,他向我吐口水(列表中的一行)现在发生的事情Jorge 14当我离开学校时,他向我吐口水。(列