代码之家  ›  专栏  ›  技术社区  ›  jp2code

如何使用系统验证用户名/密码。DirectoryServices。协议

  •  4
  • jp2code  · 技术社区  · 8 年前

    首先,我不能使用 Active Directory ,因此我无法使用 System.DirectoryServices 直接地这将是一台PC向Novell网络发送查询,其中 System.DirectoryServices.Protocol 支持。

    我非常确信,我现在需要提供适当的搜索请求。

    这就是我目前的情况:

    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
    };
    
    2 回复  |  直到 8 年前
        1
  •  5
  •   ClownCoder    8 年前

    让我向您展示我为实现此验证所做的最佳尝试,也许它会对您有用。

    在我的上下文中,这不起作用,因为我的管理员用户无法读取属性“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.");
            }
    
        2
  •  1
  •   Community Mohan Dere    6 年前

    在Windows上

    您可以附加 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;
    }
    

    资料来源:


    关于Novell

    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 .