【问题标题】:LDAP authentication on Apache against hashed passwordApache 上针对散列密码的 LDAP 身份验证
【发布时间】:2014-08-07 14:42:33
【问题描述】:

我有一个带有 apache HTTP 服务器前端的 tomcat 服务器的设置。 Apache 服务器使用 LDAP 进行身份验证。

我正在使用嵌入式 LDAP 服务器 (Apache DS),并已配置为使用

禁用匿名绑定
service.setAllowAnonymousAccess(false); // Disable Anonymous Access

service.setAccessControlEnabled(true); // Enable basic access control check (allow only  System Admin to login to LDAP Server)

我的应用程序使用 Spring LDAP 连接并执行用户操作,例如添加用户。我在spring.xml中配置如下:

  <bean id="ldapContextSource" class="org.springframework.ldap.core.support.LdapContextSource">
           <property name="url" value="ldap://localhost:389" />
           <property name="base" value="dc=test,dc=com" />
           <property name="userDn" value="uid=admin,ou=system" />
           <property name="password" value="secret" />
      </bean>

Apache httpd.conf 配置为使用基本身份验证

AuthLDAPBindDN "uid=admin,ou=system"
AuthLDAPBindPassword "{SHA}<Hash for secret>"

问题 1:尝试使用客户端(例如 jexplorer)登录 ldap 服务器时,我可以使用散列密码和纯文本“秘密”登录。这怎么可能?

在这种情况下,如果有人知道 AuthLDAPBindDN 和 AuthLDAPBindPassword(在我的情况下是散列的),他们将能够使用它们登录到具有完全访问权限的 LDAP 服务器,这是一个安全威胁。

另外,我想用散列的密码替换 spring.xml 中的密码。由于管理员可以更改 LDAP 密码,我如何确保我的应用程序使用更新后的哈希密码,因为我们在 spring.xml 中对其进行了硬编码?

【问题讨论】:

标签: java apache authentication hash spring-ldap


【解决方案1】:

关于您的第二个问题:您通常不应该在 XML 文件中硬编码服务器 URL、用户名、密码等内容。这些东西通常应该外部化到属性文件并使用&lt;context:property-placeholder&gt; 处理。例如,假设您有一个包含以下内容的属性文件:

ldap.server.url=ldap://localhost:389
ldap.base=dc=test,dc=com
ldap.userDn=uid=admin,ou=system
ldap.password=secret

然后您可以在配置文件中引用这些属性,例如:

 <context:property-placeholder ignore-resource-not-found="true"
                               location="classpath:/ldap.properties,
                                         file:/etc/mysystem/ldap.properties" />

 <bean id="ldapContextSource" class="org.springframework.ldap.core.support.LdapContextSource">
       <property name="url" value="${ldap.server.url}" />
       <property name="base" value="${ldap.base}" />
       <property name="userDn" value="${ldap.userDn}" />
       <property name="password" value="${ldap.password}" />
  </bean>

Spring 会自动将 ${} 中的内容替换为您的属性文件中的相应值。

请注意,我在&lt;context:property-placeholder&gt; 元素中指定了两个属性文件位置,并且我还包括了ignore-resource-not-found="true"。这很有用,因为它使您可以在源代码中包含属性文件以进行简单的开发设置,但在生产中,如果您将属性文件放在 /etc/mysystem/ldap.properties 下,这将覆盖捆绑属性文件中的内容。

这样,如果在生产环境中被admin修改密码,只需要修改properties文件即可;您不需要重新构建应用程序。

关于为什么 apache DS 接受散列密码;一个原因可能是您的 LDAP 服务器设置为接受匿名访问以进行读取操作,这意味着它实际上在您阅读时根本不进行身份验证。不过可能是其他问题,您必须将问题直接提交给 Apache DS 支持。

【讨论】:

  • 根据 Apache DS 文档,传递散列密码而不是普通密码的场景不应该允许登录,但在我的情况下它可以。关于第二个问题,我同意将内容移动到属性文件将是一个不错的选择,但即便如此要连接到 LDAP,我也需要传递我不想存储在属性文件中的纯文本。春天有没有办法,我可以读取属性文件(存储加密密码),对获取的值进行后处理以解密并传递给 spring.xml 中的 Ldap 配置
  • 您可以使用自定义BeanFactoryPostProcessor 来做到这一点。您定义一个类似于属性替换策略的自定义语法(例如%hashedPassword%),并让您的 BeanFactoryPostProcessor 识别这些属性值并在启动时解密它们。然而,我认为这并不更安全——充其量只是默默无闻的安全;解密逻辑需要包含在您的应用程序中,因此如果有人想解密它仍然是可能的。
猜你喜欢
  • 2016-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-31
  • 1970-01-01
  • 2018-02-09
相关资源
最近更新 更多