将一个32字符的http会话id缩短为20个字符(truncate?hash?)

时间:2012-11-21 10:01:09

标签: java http function session hash

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

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

如果ID确实是随机的,我理论上可以将它截断为20个字符吗?但由于我不确切知道如何生成此ID,因此最好使用散列函数将ID分解为20个字符。

您是否有关于哈希函数的建议或有关HttpSession ID的更多信息可以帮助我解决这个问题?

提前致谢。

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

我创建了一个char []数组,其中包含所有未保留的百分比编码字符。我只接受未预留的字符,因为保留的字符在编码时占用3个时隙: 例如'/'是'%2F'

然后我从十六进制字符串中创建一个字节数组,这给了我一个字节[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包含字母A-Z,a-Z,0-9和-_。〜

1 个答案:

答案 0 :(得分:5)

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