首先,我无法使用 Active Directory ,因此我无法直接使用System.DirectoryServices
。这将是一台PC向仅支持System.DirectoryServices.Protocol
的Novell网络发送查询。
我很确定我需要提供正确的SearchRequest。
这是我到目前为止所做的:
private static String _certificatePath;
private static String _server;
private static SearchResponse Query(String user, String pwd, out String error)
{
SearchResponse result = null;
error = String.Empty;
if (File.Exists(_certificatePath))
{
var identifier = new LdapDirectoryIdentifier(_server, false, false);
try
{
using (var connection = new LdapConnection(identifier))
{
connection.SessionOptions.ProtocolVersion = 3;
var cert = new X509Certificate();
cert.Import(_certificatePath, null, X509KeyStorageFlags.DefaultKeySet);
connection.ClientCertificates.Add(cert);
connection.AuthType = AuthType.External;
connection.AutoBind = false;
var request = new SearchRequest()
{
DistinguishedName = user, //Find this person
Filter = "(objectClass=*)", //The type of entry we are looking for
Scope = System.DirectoryServices.Protocols.SearchScope.Subtree, //We want all entries below this ou
};
result = (SearchResponse)connection.SendRequest(request); //Run the query and get results
}
} catch (Exception err)
{
error = String.Format("SDSP::Query {0}: {1}", err.GetType(), err.Message);
}
}
else
{
error = "The system cannot find the Cryptography Certificate at the path specified in the Application Configuration file.";
}
return result;
}
如何创建SearchRequest来验证user
/ pwd
组合?
var request = new SearchRequest()
{
DistinguishedName = user, //Find this person
Filter = "(objectClass=*)", //The type of entry we are looking for
Scope = System.DirectoryServices.Protocols.SearchScope.Subtree, //We want all entries below this ou
};
答案 0 :(得分:3)
让我告诉你我最好的尝试来实现这个验证,也许它适合你。
在我的上下文中,这不起作用,因为我的管理员用户无法读取属性“userPassword”,我无法理解原因。我猜是没有分配一些许可。
无论如何这是代码,希望它有所帮助:
var server = "<SERVER:PORT>";
var adminUser = "<USERNAME>";
var adminPass = "<PASSWORD>";
using (var ldap = new LdapConnection(server))
{
ldap.SessionOptions.ProtocolVersion = 3;
// To simplify this example I'm not validating certificate. Your code is fine.
ldap.SessionOptions.VerifyServerCertificate += (connection, certificate) => true;
ldap.SessionOptions.SecureSocketLayer = true;
ldap.AuthType = AuthType.Basic;
ldap.Bind(new System.Net.NetworkCredential($"cn={adminUser},o=<ORGANIZATION>", adminPass));
// Now I will search to find user's DN.
// If you know exact DN, then you don't need to search, go to compare request directly.
var search = new SearchRequest
{
//Here goes base DN node to start searching. Node closest to entry improves performance.
// Best base DN is one level above.
DistinguishedName = "<BASEDN>", //i.e.: ou=users,o=google
Filter = "uid=<USERNAME>",
Scope = SearchScope.OneLevel
};
// Adding null to attributes collection, makes attributes list empty in the response.
// This improves performance because we don't need any info of the entry.
search.Attributes.Add(null);
var results = (SearchResponse)ldap.SendRequest(search);
if (results.Entries.Count == 0)
throw new Exception("User not found");
// Because I'm searching "uid" can't exists more than one entry.
var entry = results.Entries[0];
// Here I use DN from entry found.
var compare = new CompareRequest(entry.DistinguishedName, new DirectoryAttribute("userPassword", "<PASSWORD>"));
var response = (CompareResponse)ldap.SendRequest(compare);
if (response.ResultCode != ResultCode.CompareTrue)
throw new Exception("User and/or Password incorrect.");
}
答案 1 :(得分:1)
您可以为ContextOptions.Negotiate
附加ValidateCredentials
参数(用户名和密码)。
const int ldapErrorInvalidCredentials = 0x31;
const string server = "sd.example.com:636";
const string domain = "sd.example.com";
try
{
using (var ldapConnection = new LdapConnection(server))
{
var networkCredential = new NetworkCredential(_username, _password, domain);
ldapConnection.SessionOptions.SecureSocketLayer = true;
ldapConnection.AuthType = AuthType.Negotiate;
ldapConnection.Bind(networkCredential);
}
// If the bind succeeds, the credentials are valid
return true;
}
catch (LdapException ldapException)
{
// Invalid credentials throw an exception with a specific error code
if (ldapException.ErrorCode.Equals(ldapErrorInvalidCredentials))
{
return false;
}
throw;
}
DirectoryEntry和DirectorySearcher都是高级类工具,是Active Directory的包装器。
//use the users credentials for the query
DirectoryEntry root = new DirectoryEntry(
"LDAP://dc=domain,dc=com",
loginUser,
loginPassword
);
//query for the username provided
DirectorySearcher searcher = new DirectorySearcher(
root,
"(sAMAccountName=" + loginUser + ")"
);
//a success means the password was right
bool success = false;
try {
searcher.FindOne();
success = true;
}
catch {
success = false;
}
提到answer。