2012-03-28 7 views
6

Xuân 3.1 Tomcat 6. *mùa xuân quá trình xác thực LDAP 3.1: "Credentials Bad" msg Khi Credentials Are Tốt

tôi đang làm việc trên thực hiện một webapp Xuân 3.1, chứng thực với LDAP.

Tôi đã kiểm tra thông tin đăng nhập LDAP (tên người dùng, mật khẩu, URL ldap, mẫu tìm kiếm) bằng chương trình Java theo kiểu JNDI tôi đã viết (được trích dẫn bên dưới). Chương trình đó đã hoạt động, đã đổ tất cả các thuộc tính của người dùng, bao gồm cả mật khẩu, dường như được mã hóa trên máy chủ LDAP.

Khi tôi cố đăng nhập bằng thông tin đăng nhập tương tự trong Spring 3.1, tôi nhận được thông báo lỗi "Bad Credentials".

tôi nhận được tin nhắn này trong các bản ghi:

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 

Trong * -security.xml của tôi, tôi đã cố gắng sử dụng các thẻ để thực hiện một so sánh mật khẩu và mã hóa xảy ra, nhưng nó đã không giúp đỡ. Tôi đã thử sử dụng md4, md5, plaintext, sha, sha-256, {ssha}, {sha} không có kết quả.

<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> 

Nhóm mạng của tôi là tổ chức quan trọng, chậm, quan liêu. Có cách nào tôi có thể nói những gì họ sử dụng mã hóa, nếu có, mà không cần liên lạc với họ?

Bất kỳ ý tưởng nào về những điều tôi có thể xem?

Đây là * -security.xml của tôi như là của nỗ lực cuối cùng của tôi và bản demo java LDAP tôi đã có thể kết nối với

Cảm ơn.

file * -security.xml của tôi:

<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> 

Đây là phong cách JNDI chương trình LDAP Java làm việc với các thông tin tương tự:

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 

Solution


Nhận xét này từ Luke Taylor đã giúp tôi có được làm việc cấu hình của tôi:

cấu hình của bạn là sai ở chỗ bạn có "o = acme.com" trong URL máy chủ LDAP và cũng đang sử dụng " o = acme.com "trong mẫu DN của người dùng.

Tôi lấy mẫu "o = acme.com" ra khỏi mẫu DN và LDAP đã hoạt động. Ban đầu tôi đã đặt "o = acme.com" trong cả URL LDAP và mẫu DN vì tôi mới sử dụng Spring 3.1 và LDAP, và điều này tương tự như cách được thực hiện trong phiên bản Java JNDI của LDAP demo tôi đã viết dựa trên mã di sản mà tôi đang thay thế.

Đây là phiên bản hoạt động cuối cùng của * bảo mật của tôi.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> 

Tôi sẽ khám phá nhận xét khác của anh ấy và xem liệu tôi có thể đặt lại mật khẩu hoặc nếu tôi cần.

+0

Một lưu ý khác. Bạn không thể đặt mã hóa mật khẩu trở lại, vì bạn không biết thuật toán nào máy chủ đang sử dụng và thực tế nó có thể đang sử dụng nhiều hơn một thuật toán. Hashing mật khẩu là về bảo vệ cơ sở dữ liệu mật khẩu bằng cách làm cho nó khó đọc hơn. Nó không phải là về làm cho xác thực khách hàng an toàn hơn (bạn sẽ tìm thấy nhiều cuộc thảo luận về điều này trên SO). Nếu bạn muốn ngăn chặn nghe lén trên mạng từ ứng dụng của bạn đến máy chủ LDAP, thì việc sử dụng kết nối SSL có lẽ là tùy chọn đơn giản nhất. –

Trả lời

3

dụ Java bạn đang sử dụng xác thực bind tiêu chuẩn, nhưng bạn đã thiết lập các cấu hình Spring Security để làm một LDAP compare operation vào mật khẩu của người dùng. Điều này sẽ không thành công vì máy chủ LDAP không sử dụng cùng một định dạng mã hóa mật khẩu như bộ mã hóa MD5 của Spring Security. Để hoạt động so sánh thành công, giá trị được lưu trữ phải khớp với chuỗi được gửi đến thư mục. Trong hầu hết các trường hợp, bạn muốn sử dụng xác thực LDAP (bind) chuẩn. Có thể bạn sẽ cần sử dụng cấu hình bean cho nhà cung cấp xác thực. Hãy thử sử dụng:

<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> 

Tôi khuyên bạn cũng nên đọc the LDAP chapter of the reference manual.

Ngoài ra, nếu bạn muốn biết lý do tại sao xác thực bị lỗi, địa điểm tốt nhất để tìm ra là nhật ký cho chính máy chủ LDAP. Nếu bạn không có quyền truy cập đầy đủ, sau đó tìm hiểu cách nó được thiết lập và sử dụng một máy chủ cục bộ (như OpenLDAP), nơi bạn có toàn quyền kiểm soát.

+0

Xin chào Luke. Tôi đã đọc chương LDAP trong Spring 3.1 vài lần. Nó là ngắn gọn và tôi mới đến LDAP cũng như mùa xuân. Tôi muốn chắc chắn rằng tôi hiểu bình luận của bạn. Nếu loại bỏ các thẻ tôi sẽ thả xuống để sử dụng ràng buộc tiêu chuẩn, như chương trình Java được trích dẫn là và tôi sẽ KHÔNG thực hiện so sánh mật khẩu? Spring có thực hiện so sánh mật khẩu theo mặc định không? Tôi có cần phải thiết lập một cái gì đó cho nó để không làm điều đó? – Steve

+0

Không liên lạc được với họ, bạn không thể, và so sánh mật khẩu không phải là một ý tưởng tuyệt vời nếu chúng được mã hóa (ví dụ như trường hợp có thể khác). Bạn nên sử dụng xác thực liên kết vì bạn đã chứng minh rằng các công trình và quên mật khẩu so sánh. Nó thường chỉ được sử dụng khi bind bị vô hiệu hóa. Bạn đã thử cấu hình tôi đã cung cấp chưa? Nếu vậy, chuyện gì đã xảy ra? –

+0

Luke, trong ánh sáng của các ý kiến ​​của bạn tôi đã thay đổi * server.xml của tôi và toàn bộ bài viết gốc của tôi. Tôi cần nghiên cứu cấu hình của bạn một chút. Nếu có thể, tôi muốn tìm cách viết phong cách Spring 3.1. Tôi sẽ cung cấp cho nó một shot và cho bạn biết làm thế nào nó hoạt động. Cảm ơn một tấn. – Steve

0

Tôi sẽ cố gắng may mắn. Vài tuần trước, tôi đã có một vấn đề tương tự. Không có lỗi, lỗi người dùng/thông báo lỗi và thông tin xác thực không hợp lệ.

Trước tiên, tôi khuyên bạn nên kích hoạt cấp độ gỡ lỗi cho bảo mật mùa xuân. Bạn sẽ nhận được nhiều thông tin hơn. Trong trường hợp của tôi, điều này đã giúp tôi thấy rằng vấn đề là người dùng của tôi không có bất kỳ vai trò nào được liên kết và Spring đã truyền nó thành lỗi "thông tin đăng nhập không hợp lệ". Nó có thể là trường hợp của bạn. Kiểm tra nó.

Dù sao, thông tin xác thực không có nghĩa là luôn luôn người dùng/vượt qua không chính xác.

EDIT: Đối với hoạt độ debug sử dụng log4j:

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

Trong cấu hình bạn, nó có thể được đọc truy cập đó để chào đón trang đòi hỏi vai trò admin: ROLE_ADMIN. Nếu bạn không muốn vai trò, bạn nên thử một cái gì đó như thế này:

<s:intercept-url pattern="/welcome*" access="isAuthenticated()" /> 
+0

Tôi mới sử dụng Spring và LDAP. Làm cách nào để kích hoạt cấp gỡ lỗi trong Spring Security? Có thể KHÔNG liên kết vai trò với người dùng và nếu như vậy thì sao? Tôi có thể liên kết vai trò trung lập với người dùng không? Chúng tôi thực sự không có vai trò cho người dùng. – Steve

+0

Tôi đã chỉnh sửa câu trả lời. Nếu bạn không muốn vai trò, đừng liên kết một vai trò với quyền truy cập. – jddsantaella

+0

Tôi đã thử giá trị quyền truy cập mới mà bạn đã đề xuất. Không thay đổi. Tôi sẽ đặt nhật ký xml mà bạn trích dẫn ở đâu? – Steve