zoukankan      html  css  js  c++  java
  • 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/

     

     

     

     

  • 相关阅读:
    C#脚本引擎 CS-Script 之(一)——初识
    系分过了,mark一下,就从这里开始吧
    Git.Framework 框架随手记-- 分享一个"比较垃圾"的项目
    Android--多选自动搜索提示
    Android--自动搜索提示
    Android--图片集
    Android--下拉框
    SQL Server 收缩日志
    Android--按钮点击事件
    Android--TextView 文字显示和修改
  • 原文地址:https://www.cnblogs.com/hlxt548826/p/3671098.html
Copyright © 2011-2022 走看看