[C#]LDAP驗證用戶名和密碼

測試環境:VS2008, NET Framework 3.5node

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

首先咱們假設LDAP的server IP是127.0.0.1ui

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

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

對應密碼是sysuserget

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

1、鏈接LDAP sever

如今咱們來測試下是否能正確鏈接到LDAP server,代碼以下:it

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);
 
try
{
object native = entry.NativeObject;
return true;
}
catch (System.Exception ex)
{
throw new Exception("Error authenticating user." + ex.Message);
}
return false;
 
 

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

2、列舉全部user

如今能鏈接到LDAP了,咱們須要取出公司的全部User,代碼以下:ast

public List<string> EnumerateOU()
{
List<string> lst = new List<string>();
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);
 
try
{
object native = entry.NativeObject;
DirectorySearcher searcher = new DirectorySearcher(entry);
searcher.Filter = "(objectClass=account)";
searcher.PropertiesToLoad.Add("cn");
SearchResultCollection ret = searcher.FindAll();
foreach (SearchResult sr in ret)
{
if (sr != null)
{
lst.Add(sr.Properties["cn"][0].ToString());
}
}
}
catch (System.Exception ex)
{
}
return lst;
}

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

LDAP://127.0.0.1/ou=user,….這個是能夠取得數據的地址。若是這裏ou爲其餘值,則拿到的就是另一些數據了。

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

全部員工應該有個共同的屬性,就拿這個共同的屬性出來。下面的searcher.Filter也是這樣,全部的員工都有個objectClass,它的值能夠有多個,但必定都有個值=account,根絕這個規則,咱們就能夠拿出全部account了。

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

咱們能夠將循環改爲這樣:

foreach (SearchResult sr in ret)
{
foreach (string key in sr.Properties.PropertyNames)
{
foreach (object val in sr.Properties[key])
{
string strTmp = key + " = " + val;
Debug.WriteLine(strTmp);
}
}
}

這樣你就能夠看到全部屬性和它存儲的value了。

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

如今咱們來檢測一下某個用戶名是否存在:

public int IsAuthenticated(string strUserName, string strPwd)
{
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);
 
try
{
object native = entry.NativeObject;
DirectorySearcher searcher = new DirectorySearcher(entry);
searcher.Filter = "(cn=" + strUserName + ")";
searcher.PropertiesToLoad.Add("cn");
SearchResult ret = searcher.FindOne();
 
if (sr != null)
return 0; //succeed.
}
}
catch (System.Exception ex)
{
}
return 1; //invalid user
}

這樣咱們就能夠檢測到某個用戶名是否存在了。這裏咱們用的Filter是cn=username,實際應用時,要檢查本身用到LDAP是用哪一個屬性來存儲用戶名的,有多是uid,也有多是其餘。

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

public int IsAuthenticated(string strUserName, string strPwd)
{
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);
 
try
{
object native = entry.NativeObject;
DirectorySearcher searcher = new DirectorySearcher(entry);
searcher.Filter = "(cn=" + strUserName + ")";
searcher.PropertiesToLoad.Add("cn");
SearchResultCollection ret = searcher.FindAll();
foreach (SearchResult sr in ret)
{
if (sr != null)
{
string strPath = sr.Path;
int nIndex = strPath.LastIndexOf("/");
if (nIndex > 0)
{
strPath = strPath.Substring(nIndex + 1, strPath.Length - nIndex - 1);
entry = new DirectoryEntry(sr.Path, strPath, strPwd, AuthenticationTypes.None);
try
{
object native1 = entry.NativeObject;
return 0;
}
catch (System.Exception ex)
{
//return 2; //invalid password
}
}
}
}
 
if (ret.Count > 0)
return 2; //invalid password
}
catch (System.Exception ex)
{
throw new Exception("Error authenticating user." + ex.Message);
}
return 1; //invalid user
}

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

這裏咱們能夠看到,咱們還修改了Filter獲得的結果,如今獲得的記過一個Collection。由於一樣的用戶名,可能屬於不一樣的group,只用findone,可能只是拿到了一個結果,而這個結果可能剛好就不是咱們想要的那個user,因此用collection遍歷,就能夠萬無一失。

此次先講這麼多吧。

相關文章
相關標籤/搜索