zoukankan      html  css  js  c++  java
  • 生成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就是满足这一系列条件的算法。软件的世界没有银弹,我们只要在一定范围内找到能 解决问题的方法即可。

    System.Guid guid = System.Guid.NewGuid(); //Guid 类型                  string strGUID = System.Guid.NewGuid().ToString(); //直接返回字符串类型   

  • 相关阅读:
    java 日期格式 毫秒 表示方法
    Java的框架是什么意思
    圣思源Java视频36节练习源码分享(自己的190+行代码对比老师的39行代码)
    预装win8的笔记本如何重装win7
    Word 2013 无法撤销操作的错误
    面试经验分享(跳槽季~~~❀)
    一些可能有点用处的C#开发经验
    电子设计解决方案透视
    突破限速
    当区块链遇上Rust
  • 原文地址:https://www.cnblogs.com/xuxiaoshuan/p/3858493.html
Copyright © 2011-2022 走看看