C# -- Guid 和 字节流的关系,以及 LDAP 根据 OctetString 类型字段做查询

在之前的一篇博文中简单介绍了使用 C# 链接 AD 的方法,点击这里
其中用户姓名(DictionaryString)、用户IDOctetString)属于不同的数据类型。
DictionaryString 可以直接被程序解析成 string 类型。
然而程序接收到的 OctetString 数据却是一组字节流,我们需要将其转换为 16 进制字符串。

C# 字节流与 Guid

当我们解析字节流为 Guid 的时候,往往需要注意一下字节的顺序。

字节序

常见序有两种:

  1. Little endian将低序字节存储在起始地址
  2. Big endian将高序字节存储在起始地址

比方说有一个四字节数字 0x08070605
如果使用 Little endian 的方式存储,它存在的形式就是 05 06 07 08
如果使用 Big endian 的方式存储,它存在的形式就是 08 07 06 05

dotnet 中的 Guid 结构使用的混合字节序

dotnetGuid 使用的是一种混合字节序
Guid 实际上分为五个部分 ,并使用 - 分隔
例如 2cb7d683-17f2-434e-9c9e-7e945da33106
在转换为字节流时,前三个部分使用反序,后两个使用正序
在这里插入图片描述

字节流转换为 Guid 字符串

C# 提供简单的方法

Guid guid = new Guid(bytes);

如果是自己解析,则可以参考以下代码:

        /// <summary>
        /// 字节流转 Guid
        /// </summary>
        /// <param name="GUID"></param>
        /// <returns></returns>
        private string ByteArrToString(byte[] GUID)
        {
            String strGUID = "";
            strGUID = "";
            strGUID = strGUID + ByteToHexString((int)GUID[3] & 0xFF);
            strGUID = strGUID + ByteToHexString((int)GUID[2] & 0xFF);
            strGUID = strGUID + ByteToHexString((int)GUID[1] & 0xFF);
            strGUID = strGUID + ByteToHexString((int)GUID[0] & 0xFF);
            strGUID = strGUID + "-";
            strGUID = strGUID + ByteToHexString((int)GUID[5] & 0xFF);
            strGUID = strGUID + ByteToHexString((int)GUID[4] & 0xFF);
            strGUID = strGUID + "-";
            strGUID = strGUID + ByteToHexString((int)GUID[7] & 0xFF);
            strGUID = strGUID + ByteToHexString((int)GUID[6] & 0xFF);
            strGUID = strGUID + "-";
            strGUID = strGUID + ByteToHexString((int)GUID[8] & 0xFF);
            strGUID = strGUID + ByteToHexString((int)GUID[9] & 0xFF);
            strGUID = strGUID + "-";
            strGUID = strGUID + ByteToHexString((int)GUID[10] & 0xFF);
            strGUID = strGUID + ByteToHexString((int)GUID[11] & 0xFF);
            strGUID = strGUID + ByteToHexString((int)GUID[12] & 0xFF);
            strGUID = strGUID + ByteToHexString((int)GUID[13] & 0xFF);
            strGUID = strGUID + ByteToHexString((int)GUID[14] & 0xFF);
            strGUID = strGUID + ByteToHexString((int)GUID[15] & 0xFF);
            
            return strGUID;
        }

        /// <summary>
        /// 十进制 转 十六进制字符串
        /// </summary>
        /// <param name="kb"></param>
        /// <returns></returns>
        private static string ByteToHexString(int kb)
        {
            byte[] bytes = new byte[1];
            bytes[0] = (byte)(kb & 0xFF);
            string S = Convert.ToHexString(bytes);
            return S;
        }

Guid 字符串转为字节流

C# 提供简单的方法

Guid guid = new Guid(guidStr);
byte[] guidBytes = guid.ToByteArray();

自己解析可以参照字节流转 Guid 的方法做一个反向的操作。

LDAP 根据 OctetString 类型字段做查询

当我们想通过 Guid 字符串去查询信息的时候,会发现根本查询不到我们想要的信息。

比如 2cb7d683-17f2-434e-9c9e-7e945da33106 是小张的信息,但是当我们在过滤条件中加入 (obejctGuid = 2cb7d683-17f2-434e-9c9e-7e945da33106) 时,我们却查询不出任何东西。

使用 Acticty Directory Explorer 工具去查询,我们会发现这个工具将我们的条件进行了转换,即将 2cb7d683-17f2-434e-9c9e-7e945da33106 转换为了 \83\D6\B7\2C\F2\17NC\9C\9E\7E\94\5D\A31\06

所以我们要找一下其中的转换规则。
在这里插入图片描述

对比及解析

Guid 按照原来的顺序重新排序后,不难发现, \ 后面跟两位其实就是我们的十六进制字符串。与转换后的不同点在于红框中的几个值:
在这里插入图片描述
然而,十六进制的 4E 正好对应 ASCII 码的 N43 对应 C31 对应 1。我们不妨将所有字节都转换成 ASCII 码看一看:
在这里插入图片描述
结论很明显,转换后的 ASCII 码只保留了字母和数字。

总结来说,转换时需要遵循以下规则:

  1. 按照 Guid 的字节序规则,8-4-4-4-12 分对应 反序-反序-反序-正序-正序 去排列
  2. 将十六进制转换为 ASCII 码 ,如果转换之后是字母或者数字,则保留 ASCII 码,否则保留十六进制字符串,并在前面加 \ 标识。

代码实现

		private List<string> validChar= new List<string>{
                "0","1","2","3","4","5","6","7","8","9"
                ,"A","B","C","D","E","F","G","H","I","J","K","L","M","N"
                ,"O","P","Q","R","S","T","U","V","W","X","Y","Z"
                ,"a","b","c","d","e","f","g","h","i","j","k","l","m","n"
                ,"o","p","q","r","s","t","u","v","w","x","y","z"
        }; 
        
        /// <summary>
        /// Guid 转化为查询条件需要的结构
        /// </summary>
        /// <param name="guid"></param>
        /// <returns></returns>
        private string GuidConvertForFilter(string guid) 
        {
            string guidnew = guid.Replace("-", "");
            string result = "";
            result += ConvertHexToAscii(guidnew.Substring(6, 2));
            result += ConvertHexToAscii(guidnew.Substring(4, 2));
            result += ConvertHexToAscii(guidnew.Substring(2, 2));
            result += ConvertHexToAscii(guidnew.Substring(0, 2));

            result += ConvertHexToAscii(guidnew.Substring(10, 2));
            result += ConvertHexToAscii(guidnew.Substring(8, 2));

            result += ConvertHexToAscii(guidnew.Substring(14, 2));
            result += ConvertHexToAscii(guidnew.Substring(12, 2));

            result += ConvertHexToAscii(guidnew.Substring(16, 2));
            result += ConvertHexToAscii(guidnew.Substring(18, 2));

            result += ConvertHexToAscii(guidnew.Substring(20, 2));
            result += ConvertHexToAscii(guidnew.Substring(22, 2));
            result += ConvertHexToAscii(guidnew.Substring(24, 2));
            result += ConvertHexToAscii(guidnew.Substring(26, 2));
            result += ConvertHexToAscii(guidnew.Substring(28, 2));
            result += ConvertHexToAscii(guidnew.Substring(30, 2));
            return result;
        }

        /// <summary>
        /// 十六进制转ASCII码(ASCII码只保留字母和数字)
        /// </summary>
        /// <param name="hex"></param>
        /// <returns></returns>
        private string ConvertHexToAscii(string hex) {
            try
            {
            	// 十六进制字符串转Int
            	Int32 bt = ConvertHexToInt(hex);
                // Int转ASCII码
                char c = Convert.ToChar(bt);
                string d = c.ToString();
                if (validChar.Contains(d))
                {
                    return d;
                }
                else 
                {
                	return "\\" + hex;
                }
            }
            catch (Exception ex) 
            {
                throw new Exception("invalid hexString");
            }
        }

        /// <summary>
        /// 十六进制字符串转Int32
        /// </summary>
        /// <param name="kb"></param>
        /// <returns></returns>
        private static Int32 ConvertHexToInt(string kb)
        {
            Int32 S = Convert.ToInt32(kb, 16);
            return S;
        }
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mingvvv

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值