博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
LDAP验证用户名和密码
阅读量:4323 次
发布时间:2019-06-06

本文共 4963 字,大约阅读时间需要 16 分钟。

测试环境: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
EnumerateOU() 2 { 3 List
lst = new List
(); 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很重要。

,….这个是可以取得数据的地址。如果这里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 user21 }
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 try23 {24 object native1 = entry.NativeObject;25 return 0;26 }27 catch (System.Exception ex)28 {29 //return 2; //invalid password30 }31 }32 }33 }34  35 if (ret.Count > 0)36 return 2; //invalid password37 }38 catch (System.Exception ex)39 {40 throw new Exception("Error authenticating user." + ex.Message);41 }42 return 1; //invalid user43 }
View Code

 

我们用这个用户名和密码create一个DirectoryEntry,如果是有效的,就能create,不是有效地,就会抛出一个异常。

这里我们可以看到,我们还修改了Filter得到的结果,现在得到的记过一个Collection。因为同样的用户名,可能属于不同的group,只用findone,可能只是拿到了一个结果,而这个结果可能恰好就不是我们想要的那个user,所以用collection遍历,就可以万无一失。

这次先讲这么多吧。

 

以上文章转载于:

 

 

 

 

转载于:https://www.cnblogs.com/hlxt548826/p/3671098.html

你可能感兴趣的文章
9_2二维数组
查看>>
为django项目创建虚拟环境
查看>>
30-RoutingMiddleware介绍以及MVC引入
查看>>
【转】AB实验设计思路及实验落地
查看>>
PHP获取客户端的IP
查看>>
C# 创建单例窗体封装
查看>>
移动端报表如何获取当前地理位置
查看>>
spring 源码
查看>>
使用 opencv 将图片压缩到指定文件尺寸
查看>>
linux中~和/的区别
查看>>
在vue-cli项目中使用bootstrap的方法示例
查看>>
jmeter的元件作用域与执行顺序
查看>>
echarts学习笔记 01
查看>>
PrimeNG安装使用
查看>>
iOS 打包
查看>>
.NET Core中的数据保护组件
查看>>
华为云软件开发云:容器DevOps,原来如此简单!
查看>>
MyEclipse 快捷键(转载)
查看>>
03链栈_LinkStack--(栈与队列)
查看>>
会滚段
查看>>