2012-11-21 47 views
1

我的要求是將一個20個字符長的http會話id作爲字符串值發送到第三方腳本。所以在Java中,我得到了HttpServletRequest,然後得到了HttpSession,最後得到了32個字符的ID,看起來像這樣的2A5B2EF7B388159A6E5A7C038F6B694F。將32字符的http會話id縮短爲20個字符(截斷?散列?)

現在我的問題: 因爲我只能通過會話ID爲最大。 20字符長的URL編碼的字符串我顯然需要縮短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); 
} 

炭[] allowedSessionIdChars包含字母A-Z,A-Z,數字0-9和-_。〜

+0

你可以md5散列字符串,然後只使用前32個字符(32個十六進制字符)的20個字符。 –

+2

_「如果ID確實是隨機的,我理論上可以將它截斷爲20個字符?」 - 當然不是 - 因爲有相當多的(256^12)會話ID共享相同的前20個字符,剩餘的12個字符。 – CodeCaster

+0

當你說「20字符長字符串值」時,「char」是什麼意思?它是一個C字符,0到255之間的值,還是隻能打印字符? –

回答

5

在十六進制字符串中的每個字符2是精確配合到一個字節。所以輸出中的每個字符實際上可以包含2個輸入字符。只需遍歷輸入字符串,如下所示: dst[i] = (src[2*i] << 8) + src[2*i+1]。對於大小爲36的輸入,您將得到一個18個字符的字符串。這是您可以獲得的最大無損壓縮,因爲這是您可以填入單個字節的最大壓縮比。

+0

空字節可能需要特殊處理,並且在測試會話ID之前不一定會顯示爲問題 – artbristol

+0

如果將輸入視爲二進制數據,則不會顯示爲問題。 – SomeWittyUsername

+0

這是一個*腳本*。 – artbristol