3

Nginx 可以配置为生成适合客户端识别的 uuid。在收到来自新客户端的请求后,它会以两种形式附加一个 uuid,然后将请求上游转发到源服务器:

  • Base64 中带有 uuid 的 cookie(例如CgIGR1ZfUkeEXQ2YAwMZAg==
  • 带有十六进制 uuid 的标头(例如4706020A47525F56980D5D8402190303

我想将十六进制表示转换为等效的 Base64。我在 Ruby 中有一个可行的解决方案,但我没有完全掌握底层机制,尤其是字节顺序的切换:

hex_str = "4706020A47525F56980D5D8402190303"

将其视为高半字节(最高有效 4 位在前)二进制数据hex_str的序列,生成(ASCII 编码)字符串表示:

binary_seq = [hex_str].pack("H*")

# 47 (71 decimal) -> "G"
# 06  (6 decimal) -> "\x06" (non-printable)
# 02  (2 decimal) -> "\x02" (non-printable)
# 0A (10 decimal) -> "\n"
# ...

#=> "G\x06\x02\nGR_V\x98\r]\x84\x02\x19\x03\x03"

映射binary_seq到 32 位小端无符号整数数组。每 4 个字符(4 个字节 = 32 位)映射为一个整数:

data = binary_seq.unpack("VVVV")

# "G\x06\x02\n"      ->  167904839 (?)
# "GR_V"             -> 1449087559 (?)
# "\x98\r]\x84"      -> 2220690840 (?)
# "\x02\x19\x03\x03" ->   50534658 (?)

#=> [167904839, 1449087559, 2220690840, 50534658]

data其视为 32 位大端无符号整数数组,生成(ASCII 编码)字符串表示:

network_seq = data.pack("NNNN")

#  167904839 -> "\n\x02\x06G"      (?)
# 1449087559 -> "V_RG"             (?)
# 2220690840 -> "\x84]\r\x98"      (?)
#   50534658 -> "\x03\x03\x19\x02" (?)

#=> "\n\x02\x06GV_RG\x84]\r\x98\x03\x03\x19\x02"

network_seq在 Base64 字符串中编码:

Base64.encode64(network_seq).strip

#=> "CgIGR1ZfUkeEXQ2YAwMZAg=="

我粗略的理解是,big-endian 是网络通信的标准字节顺序,而 little-endian 在主机上更常见。为什么 nginx 提供了两种需要切换字节顺序才能转换的形式我不确定。

我也不明白.unpack("VVVV")and.pack("NNNN")步骤是如何工作的。我可以看到它G\x06\x02\n变成了\n\x02\x06G,但我不明白到达那里的步骤。例如,关注 的前 8 位hex_str,为什么做.pack(H*).unpack("VVVV")产生:

"4706020A" -> "G\x06\x02\n" -> 167904839

而直接转换为 base-10 会产生:

"4706020A".to_i(16) -> 1191576074

? 我问这个的事实表明我需要澄清所有这些转换中到底发生了什么:)

4

0 回答 0