如何在JavaScript中创建GUID(全球独特识别器)?GUID/UUID应该至少有32个字符,并且应该保持在ASCII范围内,以避免在通过它们时遇到麻烦。
我不确定在所有浏览器上有哪些习惯,如何“随机”和种植内置的随机号码发电机等。
如何在JavaScript中创建GUID(全球独特识别器)?GUID/UUID应该至少有32个字符,并且应该保持在ASCII范围内,以避免在通过它们时遇到麻烦。
我不确定在所有浏览器上有哪些习惯,如何“随机”和种植内置的随机号码发电机等。
当前回答
UUID 与内置时间标签(发行器/发行器)
我在 date.now() 中的毫秒内使用时间印(在 Node.js 图书馆中,我将稍后提到,我从 process.hrtime.bigint() 中的 nanoseconds 使用时间印),然后随机添加 5 位数(10000-90000 )到时间印链的尽头。
由于我们将时间标记插入 UUID 线上,我们获得一个功能(好或坏 - 取决于任务) - 能够轻松地从 UUID 提取此时间标记。
Node.js 编辑
基准
点击此处查看JsBench
其他回答
原始 URL.createObjectURL 正在产生 UUID. 您可以利用此。
function uuid() {
const url = URL.createObjectURL(new Blob())
const [id] = url.toString().split('/').reverse()
URL.revokeObjectURL(url)
return id
}
我找不到使用单一 16-octet TypedArray 和 DataView 的任何答案,所以我认为在 RFC 中创建版本 4 UUID 的下列解决方案将自行存在:
const uuid4 = () => {
const ho = (n, p) => n.toString(16).padStart(p, 0); /// Return the hexadecimal text representation of number `n`, padded with zeroes to be of length `p`
const data = crypto.getRandomValues(new Uint8Array(16)); /// Fill the buffer with random data
data[6] = (data[6] & 0xf) | 0x40; /// Patch the 6th byte to reflect a version 4 UUID
data[8] = (data[8] & 0x3f) | 0x80; /// Patch the 8th byte to reflect a variant 1 UUID (version 4 UUIDs are)
const view = new DataView(data.buffer); /// Create a view backed by a 16-byte buffer
return `${ho(view.getUint32(0), 8)}-${ho(view.getUint16(4), 4)}-${ho(view.getUint16(6), 4)}-${ho(view.getUint16(8), 4)}-${ho(view.getUint32(10), 8)}${ho(view.getUint16(14), 4)}`; /// Compile the canonical textual form from the array data
};
我更喜欢,因为:
它只依赖于标准 ECMAScript 平台的功能,在可能的情况下 - 这只是一个程序它只使用一个单一的泡沫,尽量减少数据的复制,这在理论上应该带来性能优势。
在写这篇文章时, getRandomValues 不是在 Node.js 中的加密对象中实施的东西,但是它具有相同的随机Bytes 功能,可以用来代替它。
我使用这个版本. 它是安全和简单的. 它不是为了产生格式化的Uids,它只是为了产生你需要的电缆的随机线条。
export function makeId(length) {
let result = '';
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
const charactersLength = characters.length;
for (let i = 0; i < length; i++) {
let letterPos = parseInt(crypto.getRandomValues(new Uint8Array(1))[0] / 255 * charactersLength - 1, 10)
result += characters[letterPos]
}
return result;
}
事实上,在非Microsoft 循环中称之为 GUID 或 UUID,只是一个 128 位数码的随机数字,而 UUID 版本号(1-5)则位于固定位置比特。
因此,当你只是在0和65535之间创建一个随机数字的集合,并编码它们时,如下:
function guid()
{
function s4()
{
return Math.floor(Math.random() * 65536).toString(16).padStart(4, '0')
} // End Function s4
return s4() + s4() + '-' + s4() + '-' + "4" + s4().substr(1) + '-' + s4() + '-' + s4() + s4() + s4();
} // End Function guid
您可以获得有效的 GUID,但由于随机实施,它不是加密安全的。
要创建一个加密安全的 GUID,您需要使用 window.crypto (或 window.msCrypto for Internet Explorer)。
这就是这样:
function cryptGuid()
{
var array = new Uint16Array(8);
(window.crypto || window.msCrypto).getRandomValues(array);
var dataView = new DataView(array.buffer);
var parts = [];
for(var i = 0; i < array.length; ++i)
{
// 0&1,2,3,4,5-7 dataView.getUint16(0-7)
if(i>1 && i<6) parts.push("-");
parts.push(dataView.getUint16(i).toString(16).padStart(4, '0'));
}
parts[5] = "4" + parts[5].substr(1);
// console.log(parts);
return parts.join('').toUpperCase();// .toLowerCase();
}
cryptGuid();
此外,您还需要决定,如果您将数字返回为下或上案字符串,某些软件需要下案字符(例如,报告服务),而其他则会产生上案字符(SQL Server)。
这里有很多正确的答案,但不幸的是,包含的代码样本是相当密码和难以理解的。
请注意,随后的代码使用二进制字母以提高可读性,因此需要ECMAScript 6。
Node.js 版本
function uuid4() {
let array = new Uint8Array(16)
crypto.randomFillSync(array)
// Manipulate the 9th byte
array[8] &= 0b00111111 // Clear the first two bits
array[8] |= 0b10000000 // Set the first two bits to 10
// Manipulate the 7th byte
array[6] &= 0b00001111 // Clear the first four bits
array[6] |= 0b01000000 // Set the first four bits to 0100
const pattern = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
let idx = 0
return pattern.replace(
/XX/g,
() => array[idx++].toString(16).padStart(2, "0"), // padStart ensures a leading zero, if needed
)
}
浏览器版本
只有第二条线是不同的。
function uuid4() {
let array = new Uint8Array(16)
crypto.getRandomValues(array)
// Manipulate the 9th byte
array[8] &= 0b00111111 // Clear the first two bits
array[8] |= 0b10000000 // Set the first two bits to 10
// Manipulate the 7th byte
array[6] &= 0b00001111 // Clear the first four bits
array[6] |= 0b01000000 // Set the first four bits to 0100
const pattern = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
let idx = 0
return pattern.replace(
/XX/g,
() => array[idx++].toString(16).padStart(2, "0"), // padStart ensures a leading zero, if needed
)
}
测试
最后,相应的测试(Jasmine)。
describe(".uuid4()", function() {
it("returns a UUIDv4 string", function() {
const uuidPattern = "XXXXXXXX-XXXX-4XXX-YXXX-XXXXXXXXXXXX"
const uuidPatternRx = new RegExp(uuidPattern.
replaceAll("X", "[0-9a-f]").
replaceAll("Y", "[89ab]"))
for (let attempt = 0; attempt < 1000; attempt++) {
let retval = uuid4()
expect(retval.length).toEqual(36)
expect(retval).toMatch(uuidPatternRx)
}
})
})
UUID v4 解释
非常好的解释 UUID 版本 4 在这里: 创建一个符合 RFC 4122 的 UUID。
最后笔记
此外,有很多第三方包. 但是,只要你只是基本的需求,我不推荐它们. 事实上,没有很多赢得和几乎失去。 作者可以追求最薄的比特的性能,“修复”的事情,不应该固定,当涉及到安全,这是一个危险的想法. 同样,他们可能会引入其他错误或不一致性。