C#生成比較短的Token字符串
有的時(shí)候,我們需要生成一些Token作為標(biāo)識(shí):如認(rèn)證后的標(biāo)識(shí)符,資源的提取碼等。一個(gè)比較常見(jiàn)的算法是生成一個(gè)GUID來(lái)作為T(mén)oken,由于GUID的隨機(jī)性和唯一性特點(diǎn),作為T(mén)oken是一個(gè)非常可靠的選擇。
GUID是一個(gè)128bit的數(shù)組,為了方便攜帶,往往需要把它表述為字符串的形式。一般把它表述為如下形式:{79FAF822-7194-4FE3-8C4F-1D99BE71BC9C}。這樣有一個(gè)弊病:太長(zhǎng)了,那么我們?nèi)绾伟阉厅c(diǎn)呢?
去掉不必要的修飾符
首先可以通過(guò)去掉無(wú)意義的括號(hào)和減號(hào)來(lái)較少長(zhǎng)度:
var token = guid.ToString("N");
這樣字符串就成為:79faf82271944fe38c4f1d99be71bc9c。感覺(jué)還是蠻長(zhǎng)的。
使用Base64編碼來(lái)表示
前面的表示方法中,是使用的16機(jī)制來(lái)表示的,如果使用Base64編碼的話,則可以進(jìn)一步壓縮字符串
var token = Convert.ToBase64String(guid.ToByteArray()).TrimEnd('=');
這樣字符串就成為:Ivj6eZRx40+MTx2ZvnG8nA??雌饋?lái)稍微好一點(diǎn)了。
換一種Token生成方式
在使用Base64方式的編碼后,Token字符串還是有20多位,有的時(shí)候還是嫌它長(zhǎng)了。由于GUID本身就有128bit,在要求有良好的可讀性的前提下,很難進(jìn)一步改進(jìn)了。那我們?nèi)绾萎a(chǎn)生更短的字符串呢?還有一種方式就是較少Token的長(zhǎng)度,不用GUID,而采用一定長(zhǎng)度的隨機(jī)數(shù),例如64bit,再用Base64編碼表示:
var rnd = new Random(); var tokenData = new byte[8]; rnd.NextBytes(tokenData); var token = Convert.ToBase64String(tokenData).TrimEnd('=');
由于這里只用了64bit,此時(shí)得到的字符串為Onh0h95n7nw的形式,長(zhǎng)度要短一半。這樣就方便攜帶多了。但是這種方式是沒(méi)有唯一性保證的。不過(guò)用來(lái)作為身份認(rèn)證的方式還是可以的(如網(wǎng)盤(pán)的提取碼)。
更進(jìn)一步
前面的算法中,長(zhǎng)度和隨機(jī)性倒是有了,但是沒(méi)有唯一性。對(duì)于需要唯一性的場(chǎng)景,則需要改寫(xiě)一下token的生成算法了,我在這里給一個(gè)簡(jiǎn)單的示例:
class Token { static Random rnd = new Random(); static int seed = 0; public static string Create() { var rndData = new byte[4]; rnd.NextBytes(rndData); var seedValue = Interlocked.Add(ref seed, 1); var seedData = BitConverter.GetBytes(seedValue); var tokenData = rndData.Concat(seedData).OrderBy(_ => rnd.Next()); return Convert.ToBase64String(tokenData.ToArray()).TrimEnd('='); } }
這里我的算法非常簡(jiǎn)單:
- token由兩部分組成,32位的隨機(jī)數(shù)+32位的序列
- 由序列保證唯一性,由隨機(jī)數(shù)保證隨機(jī)性。
- 組合后再進(jìn)行一次shuffle。
當(dāng)然,我這個(gè)算法也有一定的局限性,如:
- Token只能在4G范圍內(nèi)保證唯一
- Token只能在上下文中保證唯一
- Token不是完全隨機(jī)的
要解決這幾個(gè)問(wèn)題,實(shí)現(xiàn)在任何時(shí)候,任何位置,任何情況下產(chǎn)生的Token都具有唯一性和隨機(jī)性也是能做到的。但是,要知道的是,任何功能都是附有一定的代價(jià)的。這些條件往往帶來(lái)的代價(jià)就是Token長(zhǎng)度增加——GUID就是滿足這一系列條件的算法。軟件的世界沒(méi)有銀彈,我們只要在一定范圍內(nèi)找到能解決問(wèn)題的方法即可。
到此這篇關(guān)于C#生成Token字符串的文章就介紹到這了。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C#通過(guò)流寫(xiě)入一行數(shù)據(jù)到文件的方法
這篇文章主要介紹了C#通過(guò)流寫(xiě)入一行數(shù)據(jù)到文件的方法,涉及C#針對(duì)文本文件讀寫(xiě)的基本技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-07-07C#進(jìn)行文件讀寫(xiě)、創(chuàng)建、復(fù)制、移動(dòng)、刪除的方法
這篇文章主要介紹了C#進(jìn)行文件讀寫(xiě)、創(chuàng)建、復(fù)制、移動(dòng)、刪除的方法,涉及C#針對(duì)文件操作的常用技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-03-03C#編程獲取客戶端計(jì)算機(jī)硬件及系統(tǒng)信息功能示例
這篇文章主要介紹了C#編程獲取客戶端計(jì)算機(jī)硬件及系統(tǒng)信息功能,可實(shí)現(xiàn)針對(duì)客戶端系統(tǒng)CPU、硬盤(pán)、主板等硬件信息及客戶端操作系統(tǒng)、IP、MAC等信息的操作技巧,需要的朋友可以參考下2017-01-01C# SortedList排序列表的實(shí)現(xiàn)
本文主要介紹了C# SortedList排序列表的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-03-03C# JavaScriptSerializer序列化時(shí)的時(shí)間處理詳解
這篇文章主要為大家詳細(xì)介紹了C# JavaScriptSerializer序列化時(shí)的時(shí)間處理詳解,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08C#同步網(wǎng)絡(luò)時(shí)間的方法實(shí)例詳解
這篇文章主要介紹了C#同步網(wǎng)絡(luò)時(shí)間的方法,以實(shí)例形式較為詳細(xì)的分析了C#獲取網(wǎng)絡(luò)時(shí)間與同步本機(jī)系統(tǒng)時(shí)間的相關(guān)技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-05-05