1

我的要求是将 20 个字符长的 http 会话 ID 作为字符串值发送到第 3 方脚本。所以在Java中我得到HttpServletRequest,然后得到HttpSession,最后得到32个字符长的ID,看起来像这样2A5B2EF7B388159A6E5A7C038F6B694F。

现在我的问题是:因为我只能将会话 ID 作为最大值传递。20 字符长的 url 编码字符串我显然需要缩短 ID。如何在不增加太多冲突机会的情况下缩短 ID?

如果 ID 真的是随机的,我理论上可以将其截断为 20 个字符,对吗?但由于我不完全知道这个 ID 是如何生成的,所以最好使用一个散列函数,将 ID 分解为 20 个字符。

您对哈希函数或有关 HttpSession ID 的更多信息有什么建议,可以在这种特定情况下帮助我吗?

提前致谢。

编辑 我忘了提到 id/参数必须是 url 编码的。这种方法怎么样:

我创建了一个包含所有未保留百分比编码字符的 char[] 数组。我只使用未保留的字符,因为保留的字符在编码时最多占用 3 个插槽:例如 '/' is '%2F'

然后我从十六进制字符串中创建一个字节数组,它给了我一个 byte[16] 字节的值然后被映射(使用环绕)到具有允许字符的 char[] 数组。

StringBuilder shortenedSessionId = new StringBuilder();
char[] data = sid.toCharArray();
byte[] decodedHexData = Hex.decodeHex(data);

for (byte b : decodedHexData) {
    char mappedChar = allowedSessionIdChars[(b & 0xFF) % allowedSessionIdChars.length];
    shortenedSessionId.append(mappedChar);
}

char[] allowedSessionIdChars 包含字母 AZ、aZ、0-9 和 -_.~

4

1 回答 1

5

十六进制字符串中的每 2 个字符都完全适合一个字节。所以输出中的每个字符实际上可以容纳 2 个输入字符。只需遍历输入字符串,如下所示: dst[i] = (src[2*i] << 8) + src[2*i+1]. 对于大小为 36 的输入,您将获得一个 18 个字符的字符串。这是您可以获得的最大无损压缩,因为这是您可以填充到单个字节中的最大值。

于 2012-11-21T10:12:34.720 回答