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

cri*_*isi 1 java hash session http function

我的要求是将一个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);
}
Run Code Online (Sandbox Code Playgroud)

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

Som*_*ame 5

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