2010-03-26 22 views
13

Tôi có một ứng dụng web, nơi người dùng phải đăng nhập. Mật khẩu được lưu trữ trong máy chủ LDAP. Tất cả thông tin về máy chủ LDAP được lưu trữ trong máy chủ ứng dụng (glassfish) như tài nguyên jndi bên ngoài. Vì vậy, ứng dụng của tôi không không biết gì về máy chủ LDAP và chỉ nhận được một LdapContext như thế này:Làm thế nào để kiểm tra mật khẩu người dùng trong ldap whith java với LdapContext đã cho?

@Resource(name = "ldap/users") 
private LdapContext ctx; 

Với bối cảnh này nó rất dễ dàng để thay đổi hoặc đọc các thông tin được lưu trữ cho người dùng, nhưng làm thế nào để tôi kiểm tra mật khẩu của mình ? Thông thường tôi sẽ chỉ thực hiện một kết nối mới để kiểm tra mật khẩu người dùng. Như thế này:

Hashtable env = new Hashtable(); 
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); 
env.put(Context.PROVIDER_URL, "ldap://localhost:389/o=JNDITutorial"); 

env.put(Context.SECURITY_AUTHENTICATION, "simple"); 
env.put(Context.SECURITY_PRINCIPAL, "cn=S. User, ou=NewHires, o=JNDITutorial"); 
env.put(Context.SECURITY_CREDENTIALS, "mysecret"); 

DirContext ctx = new InitialDirContext(env); 

Nhưng vì tôi không biết thông số này, tôi không thể thực hiện việc này. Vậy làm cách nào để kiểm tra xem mật khẩu của người dùng có đúng với LdapContext của tôi không? Mật khẩu được lưu trữ mã hóa (ssha) vì vậy tôi không thể chỉ so sánh các thuộc tính.

Cảm ơn Raffael

Trả lời

8

Bạn sẽ có thể để có được môi trường từ bối cảnh ldap, sao chép nó, và sau đó đưa hiệu trưởng và các thông tin cho người dùng mà bạn muốn kiểm tra:

@Resource(name = "ldap/users") 
private LdapContext ldapContext; 

Hashtable environment = ldapContext.getEnvironment().clone(); 
environment.put(Context.SECURITY_PRINCIPAL, userDN); 
environment.put(Context.SECURITY_CREDENTIALS, userPassword); 

DirContext dirContext = new InitialDirContext(environment); 
17

này là một giải pháp có thể được sử dụng để xác thực người dùng bằng một thứ gì đó khác với DN, ví dụ: uid hoặc sAMAccountName.

Các bước làm như sau:

  1. Kết nối với máy chủ LDAP
  2. Authenticate với một người sử dụng dịch vụ của người mà chúng ta biết được DN và các thông tin
  3. Tìm kiếm người dùng mà bạn muốn để xác thực, tìm kiếm anh ta với một số thuộc tính (ví dụ: sAMAccountName)
  4. Lấy DN của người dùng chúng tôi tìm thấy
  5. Mở một kết nối khác với máy chủ LDAP với DN và mật khẩu đã tìm thấy
  6. công trình Nếu người dùng được tìm thấy và xác thực, bạn cũng tốt

Mã dụ:

public static boolean performAuthentication() { 

    // service user 
    String serviceUserDN = "cn=Mister Service,ou=Users,dc=example,dc=com"; 
    String serviceUserPassword = "abc123#!$"; 

    // user to authenticate 
    String identifyingAttribute = "uid"; 
    String identifier = "maxdev"; 
    String password = "jkl987.,-"; 
    String base = "ou=Users,dc=example,dc=com"; 

    // LDAP connection info 
    String ldap = "localhost"; 
    int port = 10389; 
    String ldapUrl = "ldap://" + ldap + ":" + port; 

    // first create the service context 
    DirContext serviceCtx = null; 
    try { 
     // use the service user to authenticate 
     Properties serviceEnv = new Properties(); 
     serviceEnv.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); 
     serviceEnv.put(Context.PROVIDER_URL, ldapUrl); 
     serviceEnv.put(Context.SECURITY_AUTHENTICATION, "simple"); 
     serviceEnv.put(Context.SECURITY_PRINCIPAL, serviceUserDN); 
     serviceEnv.put(Context.SECURITY_CREDENTIALS, serviceUserPassword); 
     serviceCtx = new InitialDirContext(serviceEnv); 

     // we don't need all attributes, just let it get the identifying one 
     String[] attributeFilter = { identifyingAttribute }; 
     SearchControls sc = new SearchControls(); 
     sc.setReturningAttributes(attributeFilter); 
     sc.setSearchScope(SearchControls.SUBTREE_SCOPE); 

     // use a search filter to find only the user we want to authenticate 
     String searchFilter = "(" + identifyingAttribute + "=" + identifier + ")"; 
     NamingEnumeration<SearchResult> results = serviceCtx.search(base, searchFilter, sc); 

     if (results.hasMore()) { 
      // get the users DN (distinguishedName) from the result 
      SearchResult result = results.next(); 
      String distinguishedName = result.getNameInNamespace(); 

      // attempt another authentication, now with the user 
      Properties authEnv = new Properties(); 
      authEnv.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); 
      authEnv.put(Context.PROVIDER_URL, ldapUrl); 
      authEnv.put(Context.SECURITY_PRINCIPAL, distinguishedName); 
      authEnv.put(Context.SECURITY_CREDENTIALS, password); 
      new InitialDirContext(authEnv); 

      System.out.println("Authentication successful"); 
      return true; 
     } 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } finally { 
     if (serviceCtx != null) { 
      try { 
       serviceCtx.close(); 
      } catch (NamingException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
    System.err.println("Authentication failed"); 
    return false; 
} 
+0

Xin chào Nikolay, tôi cũng nghĩ rằng đây là phương pháp được ưa thích vì bạn có thể tìm kiếm người dùng theo các tiêu chí khác nhau. Tôi đã thử điều này mặc dù và lấy thuộc tính 'phân biệt' luôn luôn trả về' null'. Tôi nghĩ rằng đó là một lựa chọn tốt hơn để sử dụng 'kết quả.getNameInNamespace() ', bạn nghĩ sao? – maxdev

+0

Xin chào Max, cảm ơn bạn đã tinh chỉnh giải pháp của mình. Về việc obtaing DN, tôi tin rằng nó có thể phụ thuộc vào nhà cung cấp dịch vụ LDAP. Trong trường hợp của tôi 5 năm trước đây trên cổ điển Microsoft AD LDAP nó đã làm việc thông qua khai thác thuộc tính 'attrs.get (" phân biệt tên ")'. –

1

tôi đã làm tương tự trong ứng dụng của tôi. sau đây là điều có thể hữu ích cho bạn.

package com.agileinfotech.bsviewer.servlet; 

    import java.io.IOException; 
    import javax.servlet.RequestDispatcher; 
    import javax.servlet.ServletException; 
    import javax.servlet.http.HttpServletRequest; 
    import javax.servlet.http.HttpServletResponse; 
    import javax.naming.*; 
    import javax.naming.directory.*; 
    import java.util.Hashtable; 

    public class Login extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet { 

    public Login() { 
    super(); 
    } 

    protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 

    final String SUCCESS = "loin.jsp"; 
    final String FAILURE = "Failure.html"; 
    String strUrl = "login.html"; 
    String username = request.getParameter("username"); 
    String password = request.getParameter("password"); 



    Hashtable env = new Hashtable(11); 

    boolean b = false; 

    env.put(Context.INITIAL_CONTEXT_FACTORY, 
    "com.sun.jndi.ldap.LdapCtxFactory"); 
    env.put(Context.PROVIDER_URL, "ldap://localhost:10389"); 
    env.put(Context.SECURITY_AUTHENTICATION, "simple"); 
    env.put(Context.SECURITY_PRINCIPAL, "uid="+ username +",ou=system"); 
    env.put(Context.SECURITY_CREDENTIALS, password); 

    try { 
    // Create initial context 
    DirContext ctx = new InitialDirContext(env); 

    // Close the context when we're done 
    b = true; 
    ctx.close(); 

    } catch (NamingException e) { 
    b = false; 
    }finally{ 
    if(b){ 
    System.out.print("Success"); 
    strUrl = SUCCESS; 
    }else{ 
    System.out.print("Failure"); 
    strUrl = FAILURE; 
    } 
    } 
    RequestDispatcher rd = request.getRequestDispatcher(strUrl); 
    rd.forward(request, response); 

    } 

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
    processRequest(request,response); 
    } 

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
    processRequest(request,response); 
    } 
    } 
-1

Trong máy chủ LDAP ứng dụng thực tế, mật khẩu được lưu trữ ở dạng hashcode và bất cứ khi nào quản lý truy cập mất mật khẩu từ người sử dụng, đó là mật khẩu văn bản đơn giản là một lần nữa băm với cùng một chìa khóa và kiểm tra với một lưu trong LDAP. Vì vậy, như vậy u không thể có được mật khẩu đơn giản từ máy chủ LDAP. Vì vậy, nếu bạn biết khóa bí mật, chỉ khi đó bạn mới có thể giải mã nó.

+0

Bạn không thể giải mã băm mật khẩu và không có 'khóa bí mật'. – EJP

0

Chủ đề này đã giúp tôi giải quyết trường hợp của tôi, nhờ Brandon và mel3kings khiến tôi suy nghĩ.

Các vấn đề liên quan