如何在JavaScript中创建GUID(全球独特识别器)?GUID/UUID应该至少有32个字符,并且应该保持在ASCII范围内,以避免在通过它们时遇到麻烦。
我不确定在所有浏览器上有哪些习惯,如何“随机”和种植内置的随机号码发电机等。
如何在JavaScript中创建GUID(全球独特识别器)?GUID/UUID应该至少有32个字符,并且应该保持在ASCII范围内,以避免在通过它们时遇到麻烦。
我不确定在所有浏览器上有哪些习惯,如何“随机”和种植内置的随机号码发电机等。
当前回答
这里是一个方法,使用真实的随机通过 random.org 生成 RFC4122 如果错误,它会回到浏览器的内置加密图书馆,这应该几乎是相同的好。
async function UUID() {
//get 31 random hex characters
return (await (async () => {
let output;
try {
//try from random.org
output = (await (
await fetch('https://www.random.org/integers/?num=31&min=0&max=15&col=31&base=16&format=plain&rnd=new')
).text())
//get rid of whitespace
.replace(/[^0-9a-fA-F]+/g, '')
;
if (output.length != 31)
throw '';
}
catch {
output = '';
try {
//failing that, try getting 16 8-bit digits from crypto
for (let num of crypto.getRandomValues(new Uint8Array(16)))
//interpret as 32 4-bit hex numbers
output += (num >> 4).toString(16) + (num & 15).toString(16);
//we only want 31
output = output.substr(1);
}
catch {
//failing THAT, use Math.random
while (output.length < 31)
output += (0 | Math.random() * 16).toString(16);
}
}
return output;
})())
//split into appropriate sections, and set the 15th character to 4
.replace(/^(.{8})(.{4})(.{3})(.{4})/, '$1-$2-4$3-$4-')
//force character 20 to the correct range
.replace(/(?<=-)[^89abAB](?=[^-]+-[^-]+$)/, (num) => (
(parseInt(num, 16) % 4 + 8).toString(16)
))
;
}
此分類上一篇
其他回答
// RFC 4122
//
// A UUID is 128 bits long
//
// String representation is five fields of 4, 2, 2, 2, and 6 bytes.
// Fields represented as lowercase, zero-filled, hexadecimal strings, and
// are separated by dash characters
//
// A version 4 UUID is generated by setting all but six bits to randomly
// chosen values
var uuid = [
Math.random().toString(16).slice(2, 10),
Math.random().toString(16).slice(2, 6),
// Set the four most significant bits (bits 12 through 15) of the
// time_hi_and_version field to the 4-bit version number from Section
// 4.1.3
(Math.random() * .0625 /* 0x.1 */ + .25 /* 0x.4 */).toString(16).slice(2, 6),
// Set the two most significant bits (bits 6 and 7) of the
// clock_seq_hi_and_reserved to zero and one, respectively
(Math.random() * .25 /* 0x.4 */ + .5 /* 0x.8 */).toString(16).slice(2, 6),
Math.random().toString(16).slice(2, 14)].join('-');
基于布罗法的作品,我添加了一些更多的随机性,通过添加时间表到 math.random():
function uuidv4() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
var r = parseFloat('0.' + Math.random().toString().replace('0.', '') + new Date().getTime()) * 16 | 0,
v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
根據 RFC 4122 的 UUID (Universally Unique IDentifier),也被稱為 GUID (Globally Unique IDentifier),是為提供某些獨特性保證而設計的識別。
虽然可以在JavaScript代码的几个行中实施符合RFC的UUID(例如,请参见 @broofa的答案,下面),但有几个常见的漏洞:
无效 ID 格式(UUID 必须是“xxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx”的格式,其中 x 是 [0-9, a-f] M 是 [1-5] 的格式,而 N 是 [8, 9, a 或 b] 使用低质量的随机性来源(如 Math.random)
因此,开发人员为生产环境编写代码被鼓励使用严格,良好的实施,如新模块。
来自Sagi shkedy的技术博客:
function generateGuid() {
var result, i, j;
result = '';
for(j=0; j<32; j++) {
if( j == 8 || j == 12 || j == 16 || j == 20)
result = result + '-';
i = Math.floor(Math.random()*16).toString(16).toUpperCase();
result = result + i;
}
return result;
}
还有其他方法涉及使用 ActiveX 控制,但远离这些!
我以为值得指出的是,没有GUID发电机可以保证独特的钥匙(查看维基百科文章)。总是有冲突的可能性。
下面是2011年10月9日的解决方案,由用户在https://gist.github.com/982883上发表评论:
UUIDv4 = function b(a){return a?(a^Math.random()*16>>a/4).toString(16):([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,b)}
这实现了与当前最高评级的答案相同的目标,但在50比以更少的比特中,利用强迫性、回报性和曝光性评级。
UUIDv4 =
function b(
a // placeholder
){
return a // if the placeholder was passed, return
? ( // a random number from 0 to 15
a ^ // unless b is 8,
Math.random() // in which case
* 16 // a random number from
>> a/4 // 8 to 11
).toString(16) // in hexadecimal
: ( // or otherwise a concatenated string:
[1e7] + // 10000000 +
-1e3 + // -1000 +
-4e3 + // -4000 +
-8e3 + // -80000000 +
-1e11 // -100000000000,
).replace( // replacing
/[018]/g, // zeroes, ones, and eights with
b // random hex digits
)
}