DirectoryAttribute值应该是整数而不是字符串

时间:2014-03-13 15:06:55

标签: c# ldap

我尝试使用.NET System.DirectoryServices.Protocol命名空间进行LDAP身份验证。 (这是必要的,因为我无法使用System.DirectoryServices来获取现有代码以与客户端的LDAP服务器进行通信。)

我设法使一切正常工作,但是当我尝试返回用户帐户的userAccountControl属性时,它返回值的字符串表示形式,当它应该返回时整数。 (Active Directory中的值肯定是整数。)

在以下代码中,如果我在userAccountFlags = (int)attrib[0];处断点,attrib[0]的类型是一个字符串。为什么呢?

(我很容易"修复"将其替换为int.TryParse((string)attrib[0], out userAccountFlag);但更愿意知道它为什么会发生而不是使用此解决办法。)

var ident = new LdapDirectoryIdentifier(domain, (ssl ? 636 : 389));
using (var conn = new LdapConnection(ident))
{
    conn.Credential = new NetworkCredential(domainUsername, domainPassword);
    conn.AuthType = AuthType.Basic;
    if (ssl)
    {
        conn.SessionOptions.SecureSocketLayer = true;
        conn.SessionOptions.VerifyServerCertificate = (connection, certificate) => true;
    }
    conn.Bind();

    var request = new proto.SearchRequest(rootDN, testDN, SearchScope.Subtree);
    request.Attributes.Add("userAccountControl");
    request.SizeLimit = 1;

    var response = (SearchResponse)conn.SendRequest(request);
    if (response.Entries.Count != 0)
    {
        int userAccountFlags = int.MinValue;
        foreach (proto.SearchResultEntry entry in response.Entries)
        {
            foreach (proto.DirectoryAttribute attrib in entry.Attributes.Values)
            {
                if (attrib.Name == "userAccountControl" && attrib.Count > 0)
                {
                    // The following line breaks, as "attrib[0] is string = true"
                    userAccountFlags = (int)attrib[0];
                    break;
                }
            }
        }
    }
}

2 个答案:

答案 0 :(得分:1)

从属性返回的值将始终是字符串或字节数组。

来自DirectoryAttribute indexer的文档:

  

Item的Get方法总是尝试转换并将值对象作为字符串返回;否则它返回一个字节数组。

答案 1 :(得分:0)

我可以确认Daniel是正确的。

对于您希望是整数的“ userAccountControl”和“ msDS-User-Account-Control-Computed”之类的属性,返回的DirectoryAttribute是一串字符串的字节!!

将字节转换回字符串后,可以尝试将其解析为int。

    /// <summary>
    /// Microsoft sends back ints as a string in byte form on DirectoryAttribute
    /// Because of that, we must convert bytes to string, and try to parse string to int.
    /// </summary>
    private static int TryGetAttributeValueAsInt(ref IEnumerable<DirectoryAttribute> resultAttrs, string propName)
    {
        int value = 0;
        string sInteger = TryGetAttributeValueAsString(ref resultAttrs, propName);

        if(!string.IsNullOrEmpty(sInteger))
        {
            //We will try to parse the string to an int
            if(!int.TryParse(sInteger, out value))
            {
                //Unable to parse string to int, set value to 0
                value = 0;
            }
        }

        return value;
    }

    private static string TryGetAttributeValueAsString(ref IEnumerable<DirectoryAttribute> resultAttrs, string propName)
    {
        string value = "";
        DirectoryAttribute da = resultAttrs.FirstOrDefault(r => r.Name.Equals(propName, StringComparison.OrdinalIgnoreCase));
        if (da != null && da.Count > 0)
        {
            value = da[0] as string;
        }
        return value;
    }