我正在尝试编写一个实用程序方法来更新C#中的AD属性(现在只是单值字符串属性)。这是一个不依赖IIS的独立实用程序。此方法将用于将HR系统中的数据加载到AD中。
我能够使用System.DirectoryServices.Protocols有效地读取对象和属性。但是当我调用ModifyRequest方法时,我收到带有消息&#34的DirectoryOperationException;服务器无法处理目录请求"。
基于另一个Stack Overflow问题: .Net's Directory Services throws a strange exception
我尝试将端口636用于SSL LDAP,但它不会改变行为。
我没有使用IIS,而且我使用的是.NET 4.5,因此不适用于.NET / IIS的Microsoft补丁。
谷歌搜索这一点毫无结果。
如果你知道为什么会出现这个错误,以及如何修复它,我将非常感激。
下面的代码..请假设Conn包含来自封闭实用程序类的有效且经过身份验证的LDAP连接 - 如果需要,我可以提供完整的封闭实用程序类源。
SendRequest
中的ModifyStringAttributeValues
行发生了异常:
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;
}
}
}
}
我知道代码有点笨拙,并且充满了奇怪的评论 - 在我开始工作时,它会从微软网站上的示例代码中剪切,粘贴和修改。
答案 0 :(得分:2)
如果有人再次遇到此问题,这是我的解决方案。这是删除重复的用户证书的行为,它为我解决了它。以下是步骤
certmgr.msc
personal
文件夹并找到相关证书答案 1 :(得分:1)
我的问题与不满足约束的属性值有关。我试图在帐户上设置密码而不满足所有要求(大写,包括数字等等)
答案 2 :(得分:0)
这可能是服务器证书检查的问题(例如,如果您的服务器是自动签名的)
以下是一些测试代码,用于建立绕过服务器证书检查的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;
}
答案 3 :(得分:0)
我也遇到了这个问题,可能是因为加强了域。
解决方案是使用域的协商设置进行调用,而不是简单的调用。这可能是 ValidateCredentials 中的一个错误,因为它只检查 LdapException。参见内部类Validate
的{{1}}函数中的https://github.com/dotnet/runtime/blob/main/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/Context.cs。
应该可以工作的代码: ctx.ValidateCredentials(用户名、密码、ContextOptions.Negotiate | ContextOptions.Sealing | ContextOptions.Signing);
额外的,可能是正确的信息: