C# 如何防止DirectoryOperationException-服务器无法处理目录请求

C# 如何防止DirectoryOperationException-服务器无法处理目录请求,c#,directoryservices,C#,Directoryservices,我正试图编写一个实用程序方法来更新C#中的AD属性(目前仅为单值字符串属性)。这是一个独立的实用程序,不依赖IIS。此方法将用于将人力资源系统中的数据加载到广告中 我能够使用System.DirectoryServices.Protocols有效地读取对象和属性。但是,当我调用ModifyRequest方法时,我得到一个DirectoryOperationException,消息是“服务器无法处理目录请求” 基于另一个堆栈溢出问题: 我尝试将端口636用于SSL LDAP,但它没有改变行为 我

我正试图编写一个实用程序方法来更新C#中的AD属性(目前仅为单值字符串属性)。这是一个独立的实用程序,不依赖IIS。此方法将用于将人力资源系统中的数据加载到广告中

我能够使用System.DirectoryServices.Protocols有效地读取对象和属性。但是,当我调用ModifyRequest方法时,我得到一个DirectoryOperationException,消息是“服务器无法处理目录请求”

基于另一个堆栈溢出问题:

我尝试将端口636用于SSL LDAP,但它没有改变行为

我没有使用IIS,并且在.NET 4.5上,因此.NET/IIS的Microsoft修补程序不应应用

谷歌在这方面的搜索毫无结果

如果您知道发生此错误的原因以及如何修复,我将非常感激

代码如下。。请假设Conn包含来自封闭实用程序类的有效且经过身份验证的LDAP连接——如果需要,我可以提供封闭实用程序类的完整源代码

异常发生在
ModifyStringAttributeValue
中的
SendRequest
行上:

using System;
using System.Collections.Generic;
using System.DirectoryServices.Protocols;
using System.Net;

namespace MyOrganization.Common.Ldap
{
    public class LdapSession
    {
        public bool UseKerberos { set; get; }
        public String Host { set; get; }
        public String UserId { set; get; }
        public String Password { set; get; }
        public String Tag { set; get; }
        public int Port { set; get; }

        public const int DefaultLdapPort = 389;

        protected LdapConnection Conn;

        public void EstablishV2()
        {

        }

        public void Establish()
        {

            var effectivePort = Port == 0 ? DefaultLdapPort : Port;

            Console.WriteLine("EffectivePort={0}", effectivePort);

            var identifier = new LdapDirectoryIdentifier(Host, effectivePort);

            if (UseKerberos)
            {
                Conn = new LdapConnection(identifier)
                {
                    AuthType = AuthType.Kerberos,
                    Timeout = new TimeSpan(0, 10, 0, 0),
                    SessionOptions =
                    {
                        ProtocolVersion = 3,
                        VerifyServerCertificate =
                            new VerifyServerCertificateCallback((con, cer) => true),
                        SecureSocketLayer = true
                    }
                };
            }
            else
            {
                Conn = new LdapConnection(identifier)
                {
                    AuthType = AuthType.Basic,
                    Timeout = new TimeSpan(0, 10, 0, 0)
                };

                // Console.WriteLine("LPA:  Binding with {0}, {1}", UserId, Password); // QUARTZ

                Conn.Bind(new NetworkCredential(UserId, Password));
            }


        }

        public IEnumerable<SearchResultEntry> Search(string cx, string filter, SearchScope searchScope, params string[] attrib)
        {
            var s = new SearchRequest(cx, filter, searchScope, attrib)
            {
                SizeLimit = 0,
                TimeLimit = new TimeSpan(1, 0, 0) // One hour, zero minutes, zero seconds
            };

            var raw = Conn.SendRequest(s);

            if (raw == null)
            {
                throw new Exception("null response");
            }

            var r = raw as SearchResponse;

            if (r != null)
            {
                // Console.WriteLine(Tag + "Search response entries: {0}", r.Entries.Count); // QUARTZ

                foreach (SearchResultEntry e in r.Entries)
                {
                    yield return e;
                }
            }
            else
            {
                // Console.WriteLine(Tag + "Search response was null" ); // QUARTZ
            }

            yield break;
        }


        public ResultCode ModifyStringAttributeValues(string dn, IDictionary<string, string> modifications)
        {
            // declare the request and response objects here
            // they are used in two blocks
            ModifyRequest modRequest;
            ModifyResponse modResponse;

            try
            {
                // initialize the modRequest object 
                modRequest =
                    new ModifyRequest(dn);

                modRequest.Controls.Add(new PermissiveModifyControl());

                var mods = new DirectoryAttributeModification[modifications.Count];

                int z = 0;
                foreach (var pair in modifications)
                {
                    var mod = new DirectoryAttributeModification();
                    mod.Operation = DirectoryAttributeOperation.Replace;
                    mod.Name = pair.Key;
                    mod.Add(pair.Value);

                    mods[z] = mod;

                    z += 1;
                }

                // cast the returned directory response into a ModifyResponse type 
                // named modResponse
                modResponse =
                    (ModifyResponse)Conn.SendRequest(modRequest);

                return modResponse.ResultCode;
            }

            catch (Exception e)
            {
                Console.WriteLine("\nUnexpected exception occured:\n\t{0}: {1}",
                                  e.GetType().Name, e.Message);

                return ResultCode.Unavailable;
            }
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.DirectoryServices.Protocols;
Net系统;
命名空间MyOrganization.Common.Ldap
{
公开课
{
公共bool UseKerberos{set;get;}
公共字符串主机{set;get;}
公共字符串用户标识{set;get;}
公共字符串密码{set;get;}
公共字符串标记{set;get;}
公共int端口{set;get;}
public const int DefaultLdapPort=389;
受保护的LDA连接接头;
公共图书馆v2()
{
}
公共图书馆
{
var effectivePort=Port==0?DefaultLdapPort:Port;
WriteLine(“EffectivePort={0}”,EffectivePort);
var标识符=新的LdapDirectoryIdentifier(主机、有效端口);
如果(使用Kerberos)
{
Conn=新的LdapConnection(标识符)
{
AuthType=AuthType.Kerberos,
超时=新的时间跨度(0,10,0,0),
会话选项=
{
协议版本=3,
验证服务器证书=
新的VerifyServerCertificateCallback((con,cer)=>true),
SecureSocketLayer=true
}
};
}
其他的
{
Conn=新的LdapConnection(标识符)
{
AuthType=AuthType.Basic,
超时=新的时间跨度(0,10,0,0)
};
//WriteLine(“LPA:Binding with{0},{1}”,UserId,Password);//QUARTZ
Conn.Bind(新的网络凭证(用户ID、密码));
}
}
公共IEnumerable搜索(字符串cx、字符串筛选器、SearchScope SearchScope、参数字符串[]属性)
{
var s=新的搜索请求(cx、筛选器、searchScope、attrib)
{
SizeLimit=0,
TimeLimit=newtimespan(1,0,0)//一小时零分零秒
};
var raw=连接发送请求;
如果(原始==null)
{
抛出新异常(“空响应”);
}
var r=原始响应;
如果(r!=null)
{
//Console.WriteLine(标记+“搜索响应条目:{0}”,r.entries.Count);//QUARTZ
foreach(r.Entries中的SearchResultEntry e)
{
收益率e;
}
}
其他的
{
//Console.WriteLine(标记+“搜索响应为空”);//石英
}
屈服断裂;
}
public ResultCode ModifyStringAttributeValue(字符串dn、IDictionary修改)
{
//在此处声明请求和响应对象
//它们分两个区块使用
ModifyRequest-modRequest;
ModifyResponse-modResponse;
尝试
{
//初始化modRequest对象
modRequest=
新修改请求(dn);
添加(新的PermissionModifyControl());
var mods=newdirectoryattributemodification[modifications.Count];
int z=0;
foreach(修改中的var对)
{
var mod=new DirectoryAttributeModification();
mod.Operation=DirectoryAttributeOperation.Replace;
mod.Name=pair.Key;
模加(对值);
mods[z]=mod;
z+=1;
}
//将返回的目录响应强制转换为ModifyResponse类型
//命名modResponse
模态响应=
(ModifyResponse)Conn.SendRequest(modRequest);
返回modResponse.ResultCode;
}
捕获(例外e)
{
Console.WriteLine(“\n发生意外异常:\n\t{0}:{1}”,
e、 GetType().Name,e.Message);
返回ResultCode.Unavailable;
}
}
}
}

我知道代码有点笨重,而且充满了奇怪的注释——它是在我运行时从Microsoft网站上的示例代码中剪切、粘贴和修改的。

这可能是服务器证书检查的问题(例如,如果您的服务器是自动签名的)

下面是一些绕过服务器证书检查建立SSL连接的测试代码:

public static LdapConnection GetLdapConnection(string login, string password) { var serverName = /*myServerNameFromConfig*/; var port = /*myPortFromConfig*/; LdapDirectoryIdentifier ldi = new LdapDirectoryIdentifier(string.Format("{0}:{1}", serverName, port)); NetworkCredential nc = new NetworkCredential(login, password); LdapConnection connection = new LdapConnection(ldi, nc, System.DirectoryServices.Protocols.AuthType.Basic); connection.SessionOptions.ProtocolVersion = 3; connection.SessionOptions.VerifyServerCertificate = new VerifyServerCertificateCallback((con, cer) => true); connection.SessionOptions.SecureSocketLayer = true; return connection; }