C#生成比较短的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('=');
}
}
这里我的算法非常简单:
token由两部分组成,32位的随机数+32位的序列
由序列保证唯一性,由随机数保证随机性。
组合后再进行一次shuffle。
当然,我这个算法也有一定的局限性,如:
Token只能在4G范围内保证唯一
Token只能在上下文中保证唯一
Token不是完全随机的
要解决这几个问题,实现在任何时候,任何位置,任何情况下产生的Token都具有唯一性和随机性也是能做到的。但是,要知道的是,任何功能都是附有一定的代价的。这些条件往往带来的代价就是Token长度增加——GUID就是满足这一系列条件的算法。软件的世界没有银弹,我们只要在一定范围内找到能解决问题的方法即可。
到此这篇关于C#生成Token字符串的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持易知道(ezd.cc)。
相关内容
-
字符库快捷键|字符串快捷键
字符库快捷键|字符串快捷键,,1. 字符串快捷键1、单行注释单行...
-
C# 控件BackColor = Color.Transparent没有透明
C# 控件BackColor = Color.Transparent没有透明的原因,窗体,...
-
wps中截取部分字符|请帮忙WPS表格里面截取某个
wps中截取部分字符|请帮忙WPS表格里面截取某个字符串后面的...
-
电脑十进制算法|十进制的算法教程
电脑十进制算法|十进制的算法教程,,十进制的算法教程0x10就是...
-
foreach的用法c语言和c#
foreach的用法c语言和c#,数组,遍历,本文目录foreach的用法c语...
-
伪代码描述算法
伪代码描述算法,算法,描述,伪代码,自然语言,语言,编程语言, 伪代...
-
params 是什么意思,c#里
params 是什么意思,c#里,参数,数组,本文目录params 是什么意思...
-
C# 基于StackExchange.Redis.dll利用Redis实现
C# 基于StackExchange.Redis.dll利用Redis实现分布式Session...
-
javascript对象怎么转换成字符串
javascript对象怎么转换成字符串,字符串,参数,对象,序列化,属性,数...
-
javascript如何获取字符串长度
javascript如何获取字符串长度,字符,获取,属性,字符串长度,字符串...
-
MySQL实现字符串截取的方法有哪些
MySQL实现字符串截取的方法有哪些,截取,字符串截取,有哪些,方法,...
-
php截取字符串方法有哪些
php截取字符串方法有哪些,字符串,截取,点点通,函数,支持,中文,php截...
-
javascript如何将字符串转为数组
javascript如何将字符串转为数组,数组,字符串,方法,参数,扩展,语法...
-
php中json字符串如何转csv格式
php中json字符串如何转csv格式,文件,字符串,数据,文件句柄,分隔符...
-
javascript怎么将字符串转为对象
javascript怎么将字符串转为对象,对象,字符串,格式,方法,转换,函数...