1. 程式人生 > >生成比較短的Token字串

生成比較短的Token字串

有的時候,我們需要生成一些Token作為標識:如認證後的識別符號,資源的提取碼等。一個比較常見的演算法是生成一個GUID來作為Token,由於GUID的隨機性和唯一性特點,作為Token是一個非常可靠的選擇。

GUID是一個128bit的陣列,為了方便攜帶,往往需要把它表述為字串的形式。一般把它表述為如下形式:{79FAF822-7194-4FE3-8C4F-1D99BE71BC9C}。這樣有一個弊病:太長了,那麼我們如何把它弄短點呢?

去掉不必要的修飾符,

首先可以通過去掉無意義的括號和減號來較少長度:

    var token = guid.ToString("N");

這樣字串就成為:79faf82271944fe38c4f1d99be71bc9c

。感覺還是蠻長的。

使用Base64編碼來表示

前面的表示方法中,是使用的16機制來表示的,如果使用Base64編碼的話,則可以進一步壓縮字串

    var token = Convert.ToBase64String(guid.ToByteArray()).TrimEnd('=');

這樣字串就成為:Ivj6eZRx40+MTx2ZvnG8nA。看起來稍微好一點了。

換一種Token生成方式

在使用Base64方式的編碼後,Token字串還是有20多位,有的時候還是嫌它長了。由於GUID本身就有128bit,在要求有良好的可讀性的前提下,很難進一步改進了。那我們如何產生更短的字串呢?還有一種方式就是較少Token的長度,不用GUID,而採用一定長度的隨機數,例如64bit,再用Base64編碼表示:

    var rnd = new Random();
    var tokenData = new byte[8];
    rnd.NextBytes(tokenData);
    var token = Convert.ToBase64String(tokenData).TrimEnd('=');

由於這裡只用了64bit,此時得到的字串為Onh0h95n7nw的形式,長度要短一半。這樣就方便攜帶多了。但是這種方式是沒有唯一性保證的。不過用來作為身份認證的方式還是可以的(如網盤的提取碼)。

更進一步

前面的演算法中,長度和隨機性倒是有了,但是沒有唯一性。對於需要唯一性的場景,則需要改寫一下token的生成演算法了,我在這裡給一個簡單的示例:

    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('=');
        }
    }

這裡我的演算法非常簡單:

  1. token由兩部分組成,32位的隨機數+32位的序列
  2. 由序列保證唯一性,由隨機數保證隨機性。
  3. 組合後再進行一次shuffle。

當然,我這個演算法也有一定的侷限性,如:

  1. Token只能在4G範圍內保證唯一
  2. Token只能在上下文中保證唯一
  3. Token不是完全隨機的

要解決這幾個問題,實現在任何時候,任何位置,任何情況下產生的Token都具有唯一性和隨機性也是能做到的。但是,要知道的是,任何功能都是附有一定的代價的。這些條件往往帶來的代價就是Token長度增加——GUID就是滿足這一系列條件的演算法。軟體的世界沒有銀彈,我們只要在一定範圍內找到能解決問題的方法即可。

相關推薦

生成比較Token字串

有的時候,我們需要生成一些Token作為標識:如認證後的識別符號,資源的提取碼等。一個比較常見的演算法是生成一個GUID來作為Token,由於GUID的隨機性和唯一性特點,作為Token是一個非常可靠的選擇。 GUID是一個128bit的陣列,為了方便攜帶,往往需要把它

node服務端生成七牛token

圖片資源存在自己的伺服器,客戶端訪問的時候,是非常吃頻寬的。七牛雲就很好的解決了這個問題,可以把圖片,視訊等資源存放在七牛的伺服器,自己的伺服器只提供資料,對伺服器的頻寬要求就比較低了。 1、實現流程 (1)客戶端請求伺服器,獲取token (2)客戶端使用token直接上傳到七牛雲

Python 生成一段隨機字串的三種寫法

方法1 s1=''.join(random.choice(string.ascii_letters + string.digits) for _ in range(10**7)) 方法2 for _ in range(10**7): s2 += random.choic

生成簽名,隨機字串,XML轉為陣列,陣列轉XML,json封裝,獲取IP地址

/* * ******生成簽名********* */private function getSign($params){ ksort($params); //將引數陣列按照引數名ASCII碼從小到大排序 foreach ($params as $key => $item) {

js 生成一定長度隨機字串

function randomName(len) { len = len || 23; var chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678'; var maxPos = chars.length;

ruby 生成隨機數 和 隨機字串

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

java利用UUID生成16位的字串

廢話不說  直接上程式碼 /** * 獲取16位隨機字串 * @return String */ public static String getUUID() { String uuid= UUID.randomUUID().toString(); char[]

DbForge Schema Compare for MySQL入門教程:生成比較報告

當架構比較完成後,您可以生成比較報告以保留架構更改的記錄。 1. 在“Comparison” 選單中,單擊“Generate Comparison Report” 。將開啟“Generate Comparison Report” 對話方塊。 2. 選擇要報告的報告格式

C語言:比較兩個字串是否相等

1) 使用strcmp進行比較 下面通過一個例子進行演示: #include <stdio.h> #include <string.h> int main(void) { char* str1 = "abc"; char* str2 = "a

比較兩個字串時間戳大小

問題描述:對外提供的介面,為了防止有人擷取到連結請求無限制的訪問佔用頻寬,現在要加上時間戳來校驗,只有在指定時間之內訪問的連結,才被認可。 實現方式: 比較timestamp1和timestamp2 var timestamp1 = new Date('2014-11-

C語言:strcmp比較兩個字串是否相等

#include<stdio.h> #include<string.h> //比較兩個字串是否相等,(或者說前字串比後字串不同的地方大幾) int My_strcmp( const char *str1

Delphi中accesss實現樹形結構查詢系統(一次性生成比較方便)

主要是要讀取資料庫的資訊,而delphi介面是一個樹形結構。 例如有一個Ascess資料庫:示例.MDB,內有一張表:“國家”,表的內容如下: 編號        名稱  01    

lintcode55:比較兩個字串A和B,確定A中是否包含B中所有的字元。

*樣例 給出 A = “ABCD” B = “ACD”,返回 true 給出 A = “ABCD” B = “AABC”, 返回 false 注意 在 A 中出現的 B 字串裡的字元不需要連續或

比較兩個字串A和B,確定A中是否包含B中所有的字元。

如題 樣例 給出 A = "ABCD" B = "ACD",返回 true 給出 A = "ABCD" B = "AABC", 返回 false 注意 在 A 中出現的 B 字串裡的字元不需要連續或者有序。 目前思路是分別掃描兩個字串得到兩個map&l

mybatis中使用if標籤比較兩個字串是否相等

今日一坑 轉自:http://www.cnblogs.com/a8457013/p/8033549.html 問題: mybatis中,if標籤,when標籤中都會有條件判斷:test;如何判斷兩個字串是否相等 解決: <if test="dy != null and

java生成RSA公私鑰字串,簡單易懂

java生成RSA公私鑰字串,簡單易懂   解決方法: 1.下載bcprov-jdk16-140.jar包,參考:http://www.yayihouse.com/yayishuwu/chapter/1537 2.java程式碼 KeyPairGenerator

Java學習篇之怎樣比較兩個字串

1,在程式設計中,通常比較兩個字串是否相同的表示式是“==”,但在java中不能這麼寫。在java中,用的是equals(); 例:A字串和B和字串比較: if(A.equals(B)){ } 返回true 或false. String 的equals 方法用於比較

JSP中EL表示式的比較符號、字串比較

el表示式一般不直接用==判斷是否相等 != > < >= <=之類的表示不等於 大於 小於 大於等於 小於等於, 而是使用字母表示的表示式,他們的表示如下: == eq 等於 != ne 不等於 > gt 大於 < lt 小於 >

尋找字串A中完全包含字串B的最字串

已知兩個字串a和b。字串a的字元有可能重複,字串b中的字元不重複。 編寫一個演算法,尋找字串a的最短子字串,使得該子字串包含字串b中的所有字元。 這是一道典型的動態規劃題,有點類似程式設計之美中最短摘要生成那道題目。 可以使用兩個指標t_rear和t_front遍歷字串a。

SQL生成動態交叉表+字串聚合

情景描述:因工作要求,需要做一個動態交叉表,這個比較簡單,百度有很多案例,我是參考這篇文章一個動態交叉表的範例實現的。但存在一個問題,這個動態交叉表是使用聚合函式sum()+group by進行聚合的,聚合函式sum()只能對數值型別進行聚合,而我們需要對字串型進行聚合,這就