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,代码如下:
 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。
二、列举所有user
现在能连接到LDAP了,我们需要取出公司的所有User,代码如下:
public List<string> EnumerateOU()
{
List<string> lst = new List<string>();
DirectoryEntry entry = newDirectoryEntry("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"][].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了。
三、检验某个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 ; //succeed. }
catch (System.Exception ex)
{
}
return ; //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 > )
{
strPath = strPath.Substring(nIndex + , strPath.Length - nIndex - );
entry = new DirectoryEntry(sr.Path, strPath, strPwd, AuthenticationTypes.None);
try
{
object native1 = entry.NativeObject;
return ;
}
catch (System.Exception ex)
{
//return 2; //invalid password
}
}
}
} if (ret.Count > )
return ; //invalid password
}
catch (System.Exception ex)
{
throw new Exception("Error authenticating user." + ex.Message);
}
return ; //invalid user
}
我们用这个用户名和密码create一个DirectoryEntry,如果是有效的,就能create,不是有效地,就会抛出一个异常。
这里我们可以看到,我们还修改了Filter得到的结果,现在得到的记过一个Collection。因为同样的用户名,可能属于不同的group,只用findone,可能只是拿到了一个结果,而这个结果可能恰好就不是我们想要的那个user,所以用collection遍历,就可以万无一失。
这次先讲这么多吧。
以上文章转载于:http://oliverpp.blog.163.com/blog/static/158016201211128029483/
LDAP验证用户名和密码的更多相关文章
- [C#]LDAP验证用户名和密码
		
测试环境:VS2008, NET Framework 3.5 公司打算改用LDAP来存储用户名和密码,现在用C#测试下如何能拿到LDAP中的用户名,并检测用户密码是否正确.即输入用户名和密码,可以检验 ...
 - Android 设置代理(验证用户名和密码)
		
这几天在研究在Android中,解析网页,但是公司内容,链接外网需要代理,并需要验证用户名和密码,十分头疼,网上查了下,没有头绪,最后总算在一个外国博客中看到类似的,记录下 URL url = new ...
 - django 使用form验证用户名和密码
		
form验证可以减少查询数据库,所以代码先预先验证,有问题可以返回给前端显示 1.在users文件夹下新建forms.py文件,用来验证用户名和密码是否为空,密码长度是否大于6 # -*- codin ...
 - 用SQL Server验证用户名和密码
		
用SQL Server验证用户名和密码,从页面输入的用户名和密码与数据库的用户名和密码进行匹配,正确则登入,错误则提醒. <form action="index.jsp" m ...
 - c# 调用mysql数据库验证用户名和密码
		
使用mysql数据库验证用户名和密码时,如果用户名是中文,一直查不到数据 需要把app.config 中修改为 数据库统一设置utf8编码格式,连接数据库的时候设置编码Charset=utf8可以避免 ...
 - ajax验证用户名和密码
		
var user = form.name.value; var password = form.password.value; var url = "chkname.php?user=&qu ...
 - js 验证用户名和密码是否为空
		
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"% ...
 - 验证用户名,密码,验证码,发送alax请求进行登录代码
		
//html代码 <div class="layui-form" id="larry_form"> <div class="layu ...
 - Java 验证用户名、密码
		
1. 数据库操作 2.验证用户 2.1. 查询 String sql = String.format("select count(*) from user where name='%s' a ...
 
随机推荐
- jQuery学习笔记(一)——基础选择器、过滤选择器、表单选择器
			
$()就是jQuery中的函数,它的功能是获得()中指定的标签元素.如演示样例中$("p")会得到一组P标签元素,当中"p"表示CSS中的标签选择器.$()中的 ...
 - 【Apache ZooKeeper】为ZNode设置watcher
			
众所周知,ZooKeeper中的ZNode是树形结构,现在我需要给/app1结点设置watcher,监听/app1下增减.删除和修改的结点,并将相应的事件使用log4j记录到日志文件中.ZNode的变 ...
 - oracle实现今年数据 去年同期和增长百分比
			
select c.*,round((datanow-databefore)/databefore,2)*100||'%' datapercent from (select a.auth_tztype ...
 - null类型的字段加1
			
很高兴今天学到了一种新方法. 数据库中字段类型为Long ,值可能为null,也可能是某一数.因此对该字段数值进行 +1操作时需要判断该值是null还是数值. 同时实现更新操作.具体如下: updat ...
 - JS函数作用域及作用域链理解
			
从事web开发工作,尤其主要是做服务器端开发的,难免会对客户端语言JavaScript一些概念有些似懂非懂的,甚至仅停留在实现功能的层面上,接下来的文章,是记录我对JavaScript的一些概念的理解 ...
 - 网上B2C书城,1.0javaWEB版!!好几天没更新了,都忙着做那个网站了~
			
惯例帮师傅打个广告www.java1234.com,从基础学习java WEB! 从最初的构思,到一点点功能的实现,真是不容易啊,由于自己没有项目经验,完全依靠自己的感觉,以及自己琢磨出来的思路来写, ...
 - 1.js编程风格。 --- 编写可维护的javascript
			
1. 使用4个空格字符作为一个缩进层级. 2. 不省略分号. ---> 自动插入分号机制非常复杂,且难于记忆. 3. 行的长度限定于80个字符. 4. 通常在运算符换行之后,下一行会增加两个层级 ...
 - OC语法10——@protocol协议,
			
参考资料:博客 @protocol,协议: OC中protocol的含义和Java中接口的含义是一样的,它们的作用都是为了定义一组方法规范. 实现此协议的类里的方法,必须按照此协议里定义的方法规范来. ...
 - 关于ThreadAbortExcption异常处理
			
之前程序中,使用Thread.Abort()方法来终止线程的运行,但它是抛出ThreadAbortException异常来终止线程. 异常信息摘要: Unhandled Exception:Threa ...
 - EasyUI特殊情况下的BUG整理
			
前面有两篇: Easyui - combo[tree,box]下拉图标有间隙bug解决方法 http://blog.csdn.net/isea533/article/details/12996561 ...