在Node.js中安全的随机令牌

这个问题中Erik需要在Node.js中生成一个安全的随机令牌。有一个方法crypto.randomBytes可以生成一个随机缓冲区。然而,节点中的base64编码不是url安全的,它包括/+,而不是-_。因此,我发现生成这种令牌的最简单方法是

require('crypto').randomBytes(48, function(ex, buf) {
token = buf.toString('base64').replace(/\//g,'_').replace(/\+/g,'-');
});

还有更优雅的方式吗?

278959 次浏览

试试crypto.randomBytes ():

require('crypto').randomBytes(48, function(err, buffer) {
var token = buffer.toString('hex');
});

'hex'编码在节点v0.6中工作。X或更新版本。

同步选项,以防万一,如果你不是一个JS专家像我。不得不花一些时间如何访问内联函数变量

var token = crypto.randomBytes(64).toString('hex');

1. 使用纳米类第三方库[新!]


一个微小的,安全的,url友好的,唯一的JavaScript字符串ID生成器

https://github.com/ai/nanoid

import { nanoid } from "nanoid";
const id = nanoid(48);

2. Base 64编码URL和文件名安全字母表


RCF 4648的第7页描述如何在URL安全的情况下以64进制编码。 你可以使用像base64url这样的现有库来完成这项工作

函数为:

var crypto = require('crypto');
var base64url = require('base64url');


/** Sync */
function randomStringAsBase64Url(size) {
return base64url(crypto.randomBytes(size));
}

使用的例子:

randomStringAsBase64Url(20);
// Returns 'AXSGpLVjne_f7w5Xg-fWdoBwbfs' which is 27 characters length.

注意,返回的字符串长度不会与size参数匹配(size != final length)。


3.来自有限字符集的加密随机值


注意,使用这个解决方案生成的随机字符串不是均匀分布的。

你也可以从一个有限的字符集构建一个强随机字符串,就像这样:

var crypto = require('crypto');


/** Sync */
function randomString(length, chars) {
if (!chars) {
throw new Error('Argument \'chars\' is undefined');
}


const charsLength = chars.length;
if (charsLength > 256) {
throw new Error('Argument \'chars\' should not have more than 256 characters'
+ ', otherwise unpredictability will be broken');
}


const randomBytes = crypto.randomBytes(length);
let result = new Array(length);


let cursor = 0;
for (let i = 0; i < length; i++) {
cursor += randomBytes[i];
result[i] = chars[cursor % charsLength];
}


return result.join('');
}


/** Sync */
function randomAsciiString(length) {
return randomString(length,
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789');
}

使用的例子:

randomAsciiString(20);
// Returns 'rmRptK5niTSey7NlDk5y' which is 20 characters length.


randomString(20, 'ABCDEFG');
// Returns 'CCBAAGDGBBEGBDBECDCE' which is 20 characters length.
看看real_ates ES2016的方式,它更正确。

ECMAScript 2016 (ES7)方式

import crypto from 'crypto';


function spawnTokenBuf() {
return function(callback) {
crypto.randomBytes(48, callback);
};
}


async function() {
console.log((await spawnTokenBuf()).toString('base64'));
};

< / s >

发电机/收益的方式

var crypto = require('crypto');
var co = require('co');


function spawnTokenBuf() {
return function(callback) {
crypto.randomBytes(48, callback);
};
}


co(function* () {
console.log((yield spawnTokenBuf()).toString('base64'));
});

https://www.npmjs.com/package/crypto-extra对此有一个方法:)

var value = crypto.random(/* desired length */)

随机URL和文件名字符串安全(1行)

Crypto.randomBytes(48).toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/\=/g, '');

npm模块anyid提供了灵活的API来生成各种字符串ID /代码。

使用48个随机字节在A-Za-z0-9中生成随机字符串:

const id = anyid().encode('Aa0').bits(48 * 8).random().id();
// G4NtiI9OYbSgVl3EAkkoxHKyxBAWzcTI7aH13yIUNggIaNqPQoSS7SpcalIqX0qGZ

生成由随机字节填充的固定长度的字母字符串:

const id = anyid().encode('Aa').length(20).random().id();
// qgQBBtDwGMuFHXeoVLpt

在内部,它使用crypto.randomBytes()来生成random。

查看:

var crypto = require('crypto');
crypto.randomBytes(Math.ceil(length/2)).toString('hex').slice(0,length);

最新的正确的方式使用ES 2016标准的async和await(截至节点7)异步执行此操作,将如下所示:

const crypto = require('crypto');


function generateToken({ stringBase = 'base64', byteLength = 48 } = {}) {
return new Promise((resolve, reject) => {
crypto.randomBytes(byteLength, (err, buffer) => {
if (err) {
reject(err);
} else {
resolve(buffer.toString(stringBase));
}
});
});
}


async function handler(req, res) {
// default token length
const newToken = await generateToken();
console.log('newToken', newToken);


// pass in parameters - adjust byte length
const shortToken = await generateToken({byteLength: 20});
console.log('newToken', shortToken);
}

这在Node 7中是开箱即用的,不需要任何Babel转换

使用async/await和promisification

const crypto = require('crypto')
const randomBytes = Util.promisify(crypto.randomBytes)
const plain = (await randomBytes(24)).toString('base64').replace(/\W/g, '')

生成类似VjocVHdFiz5vGHnlnwqJKN0NdeHcz8eM的东西

简单的函数,让您的标志是URL安全的,并具有base64编码!这是上面两个答案的组合。

const randomToken = () => {
crypto.randomBytes(64).toString('base64').replace(/\//g,'_').replace(/\+/g,'-');
}

crypto-random-string是一个很好的模块。

const cryptoRandomString = require('crypto-random-string');
 

cryptoRandomString({length: 10});                          // => '2cf05d94db'
cryptoRandomString({length: 10, type: 'base64'});          // => 'YMiMbaQl6I'
cryptoRandomString({length: 10, type: 'url-safe'});        // => 'YN-tqc8pOw'
cryptoRandomString({length: 10, type: 'numeric'});         // => '8314659141'
cryptoRandomString({length: 6, type: 'distinguishable'});  // => 'CDEHKM'
cryptoRandomString({length: 10, type: 'ascii-printable'}); // => '`#Rt8$IK>B'
cryptoRandomString({length: 10, type: 'alphanumeric'});    // => 'DMuKL8YtE7'
cryptoRandomString({length: 10, characters: 'abc'});       // => 'abaaccabac'

如果你想要得到一个promisecryptoRandomString.async(options)添加.async

你可以使用random-token 自由。它很容易使用。:)

var randomToken = require('random-token').create('abcdefghijklmnopqrstuvwxzyABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789');
var token = randomToken(16);

而且你也不能使用不同的盐

var randomToken = require('random-token');
var token = randomToken(16); // output -> d8d4kd29c40f021 ```

从Node.js 14.18和15.7开始,url安全的base64编码支持是内置的:

const token = crypto.randomBytes(48).toString('base64url');

如果你想使用异步版本(因为函数可能不得不等待熵),它可以被承诺更好地与现代模式对齐:

const randomBytesAsync = util.promisify(crypto.randomBytes);


const token = (await randomBytesAsync(48)).toString('base64url');

在你的终端上写

node -e "console.log(crypto.randomBytes(48).toString('hex'))"

零依赖解决方案…适用于浏览器,deno &Nodejs(带有新的全局web加密)

const random = size => btoa(
String.fromCharCode(
...crypto.getRandomValues(
new Uint8Array(size)
)
)
).replaceAll('+', 'x').replaceAll('/', 'I').slice(0, size)


for (let i = 5; i--;) console.log(random(16))