近期研究.NET环境下连接Ldap和Ldaps(ldap over ssl)的一些收获

最近一个项目,客户需要使用AD域进行统一登录认证。就一直在研究LDAP的研究,虽然不是什么新技术,但是网上的资料都比较杂。并且用户方面提供的信息也很乱。所以这段时间很煎熬。
简单说一下个人对ldap的理解,我认为ldap服务器就是一个存放用户信息的服务器。这个“服务器”有两种端口389和636。389端口属于开放端口(个人理解,可能不准确),网上的大多数方式都是连接这个端口。636端口属于加密端口。需要使用安全证书在SSL的基础上通信。
389端口的代码也比较简单,并且百度一搜有一大堆

//using System.DirectoryServices;
		public string CheckLogin(string UserName, string Password)
        {
            entry = new DirectoryEntry("LDAP://IP或域名:389(不写默认389)", @"管理员DN", @"管理员密码", AuthenticationTypes.None);
            try
            {
                object native = entry.NativeObject;
                DirectorySearcher searcher = new DirectorySearcher(entry);
                searcher.Filter = @"(name=" + UserName + ")";
                searcher.PropertiesToLoad.Add("samAccountName");
                searcher.PropertiesToLoad.Add("name");
                searcher.PropertiesToLoad.Add("userPrincipalName");
                SearchResult ret = searcher.FindOne();//查询单个用户
                //SearchResultCollection results = searcher.FindAll();//查询全部 可以配合for循环 遍历树
                //foreach (SearchResult ret in results)
                // {
                if (ret == null)
                {
                    return "未找到用户";
                }
                string strPath = ret.Path;
                int nIndex = strPath.LastIndexOf("/");
                strPath = strPath.Substring(nIndex + 1, strPath.Length - nIndex - 1);
                entry = new DirectoryEntry(ret.Path, strPath, Password, AuthenticationTypes.None);
                try
                {
                    object native1 = entry.NativeObject;//存在验证

                    ResultPropertyCollection prop = ret.Properties;//用户信息
                    string UID = prop["samAccountName"][0].ToString();
                    string UName = prop["name"][0].ToString();
                    string Email = prop["userPrincipalName"][0].ToString();
                    return "登录成功";
                }
                catch (Exception e)
                {
                    return e.Message;
                }
            }
            catch (Exception e)
            {
                return e.Message;
            }
            // return false;
        }

正常来说,一般的到这里就可以了。用户的存在验证、登录验证和树都能拿到。
但是,如果要求安全等级高的话就不行了,需要连接636端口,使用安全证书和SSL进行通讯。上面的代码我没有找到怎么使用SSL登录和证书验证。所以使用了下面的方法

//using System.DirectoryServices.Protocols;
//using System.Net;
		public string CheckLogin636(string UserName, string Password)
        {
            var host = "IP或域名:636"; 
            var baseDN = "baseDN";
            var adminName = @"用户DN";
            var adminPass = @"用户密码";// "管理密码";
            var identifier = new LdapDirectoryIdentifier(host);
            var conn = new LdapConnection(identifier, new NetworkCredential
            {
                UserName = adminName,
                Password = adminPass
            });
            conn.SessionOptions.SecureSocketLayer = true;//开启使用ssl
            conn.SessionOptions.VerifyServerCertificate = new VerifyServerCertificateCallback(ServerCallback);// 信任服务器是可以默认返回true:+= delegate { return true; };
            conn.AuthType = AuthType.Basic;
            conn.Bind();//这里不报错就是连接成功
            var request = new SearchRequest(baseDN, "(userPrincipalName=" + UserName + ")", System.DirectoryServices.Protocols.SearchScope.Subtree);
            SearchResponse response = conn.SendRequest(request) as SearchResponse;
            if (response.Entries != null && response.Entries.Count > 0)
            {
                //这里就表示 用户存在
                try
                {
                    var connUser = new LdapConnection(identifier, new NetworkCredential
                    {
                        UserName = response.Entries[0].DistinguishedName,
                        Password = Password
                    });
                    connUser.SessionOptions.SecureSocketLayer = true;
                    connUser.SessionOptions.VerifyServerCertificate = new VerifyServerCertificateCallback(ServerCallback);// 信任服务器是可以默认返回true:+= delegate { return true; };
                    connUser.AuthType = AuthType.Basic;
                    connUser.Bind();//这里不报错就是 验证登录成功
                    var attr = response.Entries[0].Attributes;//用户信息
                    string UID = attr["samAccountName"][0].ToString();
                    string UName = attr["name"][0].ToString();
                    string Email = attr["userPrincipalName"][0].ToString();
                    connUser.Dispose();
                    conn.Dispose();
                    return  "登录成功";
                }
                catch (Exception e)
                {
                    conn.Dispose();
                    if (e.Message == "The supplied credential is invalid.")
                    {
                        return "用户名或密码不正确";
                    }
                    else
                    {
                        return e.Message;
                    }
                }
            }
            else
            {
                conn.Dispose();
                return "未找到用户";
            }
        }

下面是验证证书的代码,但我验证的是一直不通过。不知道是代码的问题还是测试环境的问题。仅供参考。或者你有更好的验证方法。欢迎留言指教。

   public static bool ServerCallback(LdapConnection connection, X509Certificate certificate)
        {
            try
            {
                X509Certificate expectedCert =X509Certificate.CreateFromCertFile("证书路径");
                if (expectedCert.Equals(certificate))
                {
                    Console.WriteLine("验证成功");
                    return true;
                }
                else
                 {
                    Console.WriteLine("验证失败");
                    return false;
                }
            }
            catch (Exception ex)
            {

                Console.WriteLine("验证错误"+ex.Message);
                return false;
            }
        }

总结一点就是,一定要让客户把连接信息给清楚,确认无误。。。
以上信息学习至:
https://www.cnblogs.com/rangeon/p/7132481.html
https://www.cnblogs.com/netact/p/5742244.html
https://www.orcode.com/article/Hardware_20125929.html
基本上就这么些。文笔不好,经验不足。如果有出错或者需要改进的地方,还请不吝赐教。

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值