在Node.js中安全随机令牌

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

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

有没有更优雅的方式?

试试crypto.randomBytes() :

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

“hex”编码在节点v0.6.x或更高版本中工作。

同步选项,如果你不是像我这样的JS专家。 不得不花费一些时间来访问内联函数variables

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

1.使用URL和文件名安全字母表进行Base 64编码

RCF 4648的第7页介绍了如何使用URL安全编码64位。 您可以使用像base64url这样的现有库来完成这项工作。

该function将是:

 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. 

请注意,返回的string长度将与大小参数(大小!=最终长度)不匹配。

2.从有限的一组字符中encryption随机值

请注意,使用此解决scheme,生成的随机string不是均匀分布的。

您也可以从一组有限的字符中构build一个强大的随机string:

 var crypto = require('crypto'); /** Sync */ function randomString(length, chars) { if (!chars) { throw new Error('Argument \'chars\' is undefined'); } var charsLength = chars.length; if (charsLength > 256) { throw new Error('Argument \'chars\' should not have more than 256 characters' + ', otherwise unpredictability will be broken'); } var randomBytes = crypto.randomBytes(length); var result = new Array(length); var cursor = 0; for (var 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. 

使用ES 2016标准的asynchronous和等待(截至节点7)asynchronous执行此操作的最新正确方法如下:

 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); } 

这可以在没有任何Babel转换的节点7中使用

看看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')); }; 

发电机/发电方式

 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')); }); 

随机URL和文件名string安全(1class轮)

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

查看:

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

npm模块anyid提供灵活的API来生成各种stringID /代码。

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

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

要生成固定长度的字母表,只能用随机字节填充

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

它在内部使用crypto.randomBytes()来产生随机数。

这是一个从上面@Yves M.的回答中逐字logging的asynchronous版本

 var crypto = require('crypto'); function createCryptoString(length, chars) { // returns a promise which renders a crypto string if (!chars) { // provide default dictionary of chars if not supplied chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; } return new Promise(function(resolve, reject) { var charsLength = chars.length; if (charsLength > 256) { reject('parm chars length greater than 256 characters' + ' masks desired key unpredictability'); } var randomBytes = crypto.randomBytes(length); var result = new Array(length); var cursor = 0; for (var i = 0; i < length; i++) { cursor += randomBytes[i]; result[i] = chars[cursor % charsLength]; } resolve(result.join('')); }); } // --- now generate crypto string async using promise --- / var wantStringThisLength = 64; // will generate 64 chars of crypto secure string createCryptoString(wantStringThisLength) .then(function(newCryptoString) { console.log(newCryptoString); // answer here }).catch(function(err) { console.error(err); }); 

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

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

asynchronous/等待和promisification 。

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

生成类似于VjocVHdFiz5vGHnlnwqJKN0NdeHcz8eM