LDAP驗證用戶名和密碼


測試環境:VS2008, NET Framework 3.5

公司打算改用LDAP來存儲用戶名和密碼,現在用C#測試下如何能拿到LDAP中的用戶名,並檢測用戶密碼是否正確。即輸入用戶名和密碼,可以檢驗是否是有效的。

首先我們假設LDAP的server IP是127.0.0.1

基本的DN是ou=user,dc=companyname,dc=com

用來登錄的管理員name是cn=sysuser,ou=systemaccounts,dc=companyname,dc=com

對應密碼是sysuser

上面這些server name,user name和密碼都是測試數據,大概如此,真正用時要換成自己公司的有效server,用戶才行哦。

一、連接LDAP sever

現在我們來測試下是否能正確連接到LDAP server,代碼如下:

 

 1 DirectoryEntry entry = new DirectoryEntry("LDAP://127.0.0.1/ou=user,dc=companyname,dc=com","cn=sysuser,ou=systemaccounts,dc=companyname,dc=com", "sysuser", AuthenticationTypes.None);
 2  
 3 try
 4 {
 5   object native = entry.NativeObject;
 6   return true;
 7 }
 8 catch (System.Exception ex)
 9 {
10   throw new Exception("Error authenticating user." + ex.Message);
11 }
12 return false;
View Code

其中參數AuthenticationTypes.None一定要有,測試的時候沒有加這個,結果一直連不到server。

二、列舉所有user

現在能連接到LDAP了,我們需要取出公司的所有User,代碼如下:

 

 1 public List<string> EnumerateOU()
 2 {
 3     List<string> lst = new List<string>();
 4     DirectoryEntry entry = newDirectoryEntry("LDAP://127.0.01/ou=user,dc=companyname,dc=com","cn=sysuser,ou=systemaccounts,dc=companyname,dc=com","sysuser", AuthenticationTypes.None);
 5  
 6       try
 7     {
 8           object native = entry.NativeObject;
 9             DirectorySearcher searcher = new DirectorySearcher(entry);
10             searcher.Filter = "(objectClass=account)";
11          searcher.PropertiesToLoad.Add("cn");
12              SearchResultCollection ret = searcher.FindAll();
13             foreach (SearchResult sr in ret)
14              {
15                       if (sr != null)
16                    {
17                         lst.Add(sr.Properties["cn"][0].ToString());
18                    }
19               }
20         }
21         catch (System.Exception ex)
22        {
23      }
24       return lst;
25 }
View Code

 

這里聲明DirectoryEntry的LDAP server很重要。

LDAP://127.0.0.1/ou=user,….這個是可以取得數據的地址。如果這里ou為其他值,則拿到的就是另外一些數據了。

注意:ou=user…這句是每個公司的規則都不一樣,不一定就是ou=user,主要是遵循自己公司的規定。

所有員工應該有個共同的屬性,就拿這個共同的屬性出來。下面的searcher.Filter也是這樣,所有的員工都有個objectClass,它的值可以有多個,但一定都有個值=account,根絕這個規則,我們就可以拿出所有account了。

cn是什么呢?也是LDAP的一個屬性,這里cn里面存儲的是員工姓名。如果公司的設置不是如此,如何得知哪個node里存儲的是什么東東呢?

我們可以將循環改成這樣:

 

 1 foreach (SearchResult sr in ret)
 2 {
 3       foreach (string key in sr.Properties.PropertyNames)
 4         {
 5           foreach (object val in sr.Properties[key])
 6                 {
 7                       string strTmp = key + " = " + val;
 8                         Debug.WriteLine(strTmp);
 9           }
10         }
11 }
View Code

 

這樣你就可以看到所有屬性和它存儲的value了。

三、檢驗某個user name是否存在以及password是否正確。

現在我們來檢測一下某個用戶名是否存在:

 

 1 public int IsAuthenticated(string strUserName, string strPwd)
 2 {
 3   DirectoryEntry entry = new DirectoryEntry("LDAP://127.0.01/ou=user,dc=companyname,dc=com","cn=sysuser,ou=systemaccounts,dc=companyname,dc=com", "sysuser", AuthenticationTypes.None);
 4  
 5       try
 6         {
 7           object native = entry.NativeObject;
 8                 DirectorySearcher searcher = new DirectorySearcher(entry);
 9           searcher.Filter = "(cn=" + strUserName + ")";
10                 searcher.PropertiesToLoad.Add("cn");
11           SearchResult ret = searcher.FindOne();
12  
13               if (sr != null)
14                   return 0; //succeed.
15           
16         }
17       catch (System.Exception ex)
18         {
19   }
20       return 1; //invalid user
21 }
View Code

 

這樣我們就可以檢測到某個用戶名是否存在了。這里我們用的Filter是cn=username,實際應用時,要檢查自己用到LDAP是用哪個屬性來存儲用戶名的,有可能是uid,也有可能是其他。

但這段代碼還有個問題,它只能檢查某個用戶是否存在,但不能檢查它對應的密碼是否正確,如何可以同時檢查用戶名和密碼呢?我們修改一下代碼,如下:

 

 1 public int IsAuthenticated(string strUserName, string strPwd)
 2 {
 3 DirectoryEntry entry = new DirectoryEntry("LDAP://127.0.0.1/ou=user,dc=companyname,dc=com","cn=sysuser,ou=systemaccounts,dc=companyname,dc=com", "sysuser", AuthenticationTypes.None);
 4  
 5 try
 6 {
 7 object native = entry.NativeObject;
 8 DirectorySearcher searcher = new DirectorySearcher(entry);
 9 searcher.Filter = "(cn=" + strUserName + ")";
10 searcher.PropertiesToLoad.Add("cn");
11 SearchResultCollection ret = searcher.FindAll();
12 foreach (SearchResult sr in ret)
13 {
14 if (sr != null)
15 {
16 string strPath = sr.Path;
17 int nIndex = strPath.LastIndexOf("/");
18 if (nIndex > 0)
19 {
20 strPath = strPath.Substring(nIndex + 1, strPath.Length - nIndex - 1);
21 entry = new DirectoryEntry(sr.Path, strPath, strPwd, AuthenticationTypes.None);
22 try
23 {
24 object native1 = entry.NativeObject;
25 return 0;
26 }
27 catch (System.Exception ex)
28 {
29 //return 2; //invalid password
30 }
31 }
32 }
33 }
34  
35 if (ret.Count > 0)
36 return 2; //invalid password
37 }
38 catch (System.Exception ex)
39 {
40 throw new Exception("Error authenticating user." + ex.Message);
41 }
42 return 1; //invalid user
43 }
View Code

 

我們用這個用戶名和密碼create一個DirectoryEntry,如果是有效的,就能create,不是有效地,就會拋出一個異常。

這里我們可以看到,我們還修改了Filter得到的結果,現在得到的記過一個Collection。因為同樣的用戶名,可能屬於不同的group,只用findone,可能只是拿到了一個結果,而這個結果可能恰好就不是我們想要的那個user,所以用collection遍歷,就可以萬無一失。

這次先講這么多吧。

 

以上文章轉載於:http://oliverpp.blog.163.com/blog/static/158016201211128029483/

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM