LDAP验证用户名和密码

测试环境:VS2008, NET Framework 3.5node

公司打算改用LDAP来存储用户名和密码,如今用C#测试下如何能拿到LDAP中的用户名,并检测用户密码是否正确。即输入用户名和密码,能够检验是不是有效的。web

首先咱们假设LDAP的server IP是127.0.0.1ide

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

用来登陆的管理员name是cn=sysuser,ou=systemaccounts,dc=companyname,dc=comui

对应密码是sysuserspa

上面这些server name,user name和密码都是测试数据,大概如此,真正用时要换成本身公司的有效server,用户才行哦。code

1、链接LDAP sever

如今咱们来测试下是否能正确链接到LDAP server,代码以下:orm

 

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

2、列举全部user

如今能链接到LDAP了,咱们须要取出公司的全部User,代码以下:blog

 

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

3、检验某个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/

相关文章
相关标签/搜索