8

春天 3.1 雄猫 6.*

我正在制作一个 Spring 3.1 webapp,使用 LDAP 进行身份验证。

我使用我编写的 JNDI 风格的 Java 程序(引用如下)测试了 LDAP 凭据(用户名、密码、ldap URL、搜索模式)。该程序有效,转储了所有用户属性,包括密码,这似乎是在 LDAP 服务器上加密的。

当我尝试在 Spring 3.1 中使用相同的凭据登录时,我收到错误消息“Bad Credentials”。

我在日志中收到此消息:

DEBUG [org.springframework.security.authentication.ProviderManager:authenticate] (ProviderManager.java:152) - Authentication attempt using org.springframework.security.ldap.authentication.LdapAuthenticationProvider
DEBUG [org.springframework.security.ldap.authentication.AbstractLdapAuthenticationProvider:authenticate] (AbstractLdapAuthenticationProvider.java:51) - Processing authentication request for user: John.A.Smith
DEBUG [org.springframework.security.ldap.authentication.BindAuthenticator:bindWithDn] (BindAuthenticator.java:108) - Attempting to bind as uid=John.A.Smith,ou=People,o=acme.com,o=acme.com
DEBUG [org.springframework.security.ldap.DefaultSpringSecurityContextSource$1:setupEnvironment] (DefaultSpringSecurityContextSource.java:76) - Removing pooling flag for user uid=John.A.Smith,ou=People,o=acme.com,o=acme.com
DEBUG [org.springframework.security.ldap.authentication.BindAuthenticator:handleBindException] (BindAuthenticator.java:152) - Failed to bind as uid=John.A.Smith,ou=People,o=acme.gov: org.springframework.ldap.AuthenticationException: [LDAP: error code 32 - No Such Object]; nested exception is javax.naming.AuthenticationException: [LDAP: error code 32 - No Such Object]
DEBUG [org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter:unsuccessfulAuthentication] (AbstractAuthenticationProcessingFilter.java:340) - Authentication request failed: org.springframework.security.authentication.BadCredentialsException: Bad credentials

在我的 *-security.xml 中,我尝试使用标签进行密码比较和编码,但没有帮助。我尝试使用 md4,md5,plaintext,sha,sha-256,{ssha},{sha} 无济于事。

   <s:authentication-manager>
        <s:ldap-authentication-provider user-dn-pattern="uid={0},ou=People,o=noaa.gov" >
          <s:password-compare hash="md5">
            <s:password-encoder hash="md5"/>
          </s:password-compare>
        </s:ldap-authentication-provider>
      </s:authentication-manager>

我的网络小组是一个庞大、缓慢、官僚主义的组织。有没有一种方法可以告诉他们使用什么编码(如果有的话),而无需联系他们?

关于我可以检查的事情的任何想法?

这是我上次尝试时的 *-security.xml 以及我能够连接的 java LDAP 演示

谢谢。

我的 *-security.xml 文件:

<beans xmlns="http://www.springframework.org/schema/beans"  
  xmlns:s="http://www.springframework.org/schema/security"  
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  xsi:schemaLocation="http://www.springframework.org/schema/beans  
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
    http://www.springframework.org/schema/security  
    http://www.springframework.org/schema/security/spring-security-3.1.xsd">  



  <s:http auto-config="true" use-expressions="true">  
    **<s:intercept-url pattern="/welcome*" access="isAuthenticated()" />** 
    <s:form-login login-page="/login" default-target-url="/welcome"  
      authentication-failure-url="/loginfailed" />  
    <s:logout logout-success-url="/logout" />  
  </s:http>  



  <s:ldap-server url = "ldap://ldap-itc.sam.acme.com:636/o=acme.com"/>  

  <s:authentication-manager>
    <s:ldap-authentication-provider user-dn-pattern="uid={0},ou=People,o=noaa.gov" />
  </s:authentication-manager>

</beans>  

这是使用相同凭据工作的 JNDI 样式 LDAP Java 程序:

import javax.naming.*;  
import javax.naming.directory.*;  
import java.util.*;  
import java.sql.*;  

public class LDAPDEMO {  

    public static void main(String args[]) {  

        String lcf                = "com.sun.jndi.ldap.LdapCtxFactory";  
        String ldapurl            = "ldap://ldap-itc.sam.acme.com:636/o=acme.com";  
        String loginid            = "John.A.Smith";  
        String password           = "passowordforjohn";  
        DirContext ctx            = null;  
        Hashtable env             = new Hashtable();  
        Attributes attr           = null;  
        Attributes resultsAttrs   = null;  
        SearchResult result       = null;  
        NamingEnumeration results = null;  
        int iResults              = 0;  


        env.put(Context.INITIAL_CONTEXT_FACTORY, lcf);  
        env.put(Context.PROVIDER_URL, ldapurl);  
        env.put(Context.SECURITY_PROTOCOL, "ssl");  
        env.put(Context.SECURITY_AUTHENTICATION, "simple");  
        env.put(Context.SECURITY_PRINCIPAL, "uid=" + loginid + ",ou=People,o=acme.com");  
        env.put(Context.SECURITY_CREDENTIALS, password);  
        try {  

            ctx     = new InitialDirContext(env);  
            attr    = new BasicAttributes(true);  
            attr.put(new BasicAttribute("uid",loginid));  
            results = ctx.search("ou=People",attr);  

            while (results.hasMore()) {  
                result       = (SearchResult)results.next();  
                resultsAttrs = result.getAttributes();  

                for (NamingEnumeration enumAttributes  = resultsAttrs.getAll(); enumAttributes.hasMore();) {  
                    Attribute a = (Attribute)enumAttributes.next();  
                    System.out.println("attribute: " + a.getID() + " : " + a.get().toString());  


                }// end for loop  

                iResults++;  
            }// end while loop  

            System.out.println("iResults == " + iResults);  

        }// end try  
        catch (Exception e) {  
            e.printStackTrace();  
        }  



    }// end function main()  
}// end class LDAPDEMO  

解决方案


Luke Taylor 的这条评论帮助我让我的配置正常工作:

您的配置错误,因为您在 LDAP 服务器 URL 中有“o=acme.com”,并且还在用户 DN 模式中使用了“o=acme.com”。

我从 DN 模式中去掉了“o=acme.com”,并且 LDAP 起作用了。我最初在 LDAP URL 和 DN 模式中都添加了“o=acme.com”,因为我是 Spring 3.1 和 LDAP 的新手,这类似于 Java JNDI 版本的 LDAP我根据要替换的遗留代码编写的演示。

这是我的 *-security.xml 的最终工作版本

<beans xmlns="http://www.springframework.org/schema/beans"  
  xmlns:s="http://www.springframework.org/schema/security"  
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  xsi:schemaLocation="http://www.springframework.org/schema/beans  
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
    http://www.springframework.org/schema/security  
    http://www.springframework.org/schema/security/spring-security-3.1.xsd">  



  <s:http auto-config="true" use-expressions="true">  
    **<s:intercept-url pattern="/welcome*" access="isAuthenticated()" />** 
    <s:form-login login-page="/login" default-target-url="/welcome"  
      authentication-failure-url="/loginfailed" />  
    <s:logout logout-success-url="/logout" />  
  </s:http>  



  <s:ldap-server url = "ldap://ldap-itc.sam.acme.com:636/o=acme.com"/>  

  <s:authentication-manager>
    <s:ldap-authentication-provider user-dn-pattern="uid={0},ou=People" />
  </s:authentication-manager>

</beans>  

我将探讨他的其他评论,看看我是否可以重新输入密码编码或是否需要。

4

2 回答 2

3

您的 Java 示例使用标准绑定身份验证,但您已将 Spring Security 配置设置为对用户密码执行LDAP 比较操作。这将失败,因为 LDAP 服务器没有使用与 Spring Security 的 MD5 编码器相同的密码编码格式。要使比较操作成功,存储的值必须与发送到目录的字符串匹配。在大多数情况下,您希望使用标准 LDAP(绑定)身份验证。您可能需要为身份验证提供程序使用 bean 配置。尝试使用:

<s:ldap-server id="contextSource" url="ldap://ldap-itc.sam.acme.com:636/o=acme.com"/>

<bean id="ldapAuthProvider" class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
 <constructor-arg>
   <bean class="org.springframework.security.ldap.authentication.BindAuthenticator">
     <constructor-arg ref="contextSource"/>
     <property name="userDnPatterns">
       <list><value>uid={0},ou=People</value></list>
     </property>
   </bean>
 </constructor-arg>
 <constructor-arg>
   <bean class="org.springframework.security.ldap.authentication.NullLdapAuthoritiesPopulator"/>
 </constructor-arg>
  <property name="authoritiesMapper">
    <bean class="class="org.springframework.security.core.authority.mapping">
       <property name="defaultAuthority" value="ROLE_USER" />
    </bean>
  </property>   
</bean>

<s:authentication-manager>
  <s:authentication-manager ref="ldapAuthProvider" />
</s:authentication-manager>

我建议您也阅读参考手册的 LDAP 章节

此外,如果您想知道身份验证失败的原因,最好的查找位置是 LDAP 服务器本身的日志。如果您没有完全访问权限,请了解它的设置方式并使用您可以完全控制的本地服务器(例如 OpenLDAP)。

于 2012-04-04T12:18:22.073 回答
0

我会试试运气。几周前,我遇到了类似的问题。没有错误,正确的用户/通行证和错误的凭据错误。

首先,我建议您为 Spring Security 激活调试级别。您将获得更多信息。就我而言,这帮助我看到问题在于我的用户没有任何关联的角色,并且 Spring 将其视为“错误凭据”错误。这可能是你的情况。核实。

无论如何,错误的凭据并不意味着用户/密码总是不正确。

编辑:使用 log4j 激活调试级别:

<logger name="org.springframework.security">
    <level value="DEBUG" />
</logger>

在您的配置中,可以读取到访问欢迎页面需要管理员角色:ROLE_ADMIN。如果你不想要角色,你应该尝试这样的事情:

<s:intercept-url pattern="/welcome*" access="isAuthenticated()" />  
于 2012-03-30T21:55:00.917 回答