Javascript Node.js中的安全随机令牌
在中,Erik需要在Node.js中生成一个安全的随机令牌。有一种方法Javascript Node.js中的安全随机令牌,javascript,node.js,base64,securestring,Javascript,Node.js,Base64,Securestring,在中,Erik需要在Node.js中生成一个安全的随机令牌。有一种方法crypto.randomBytes生成一个随机缓冲区。但是,节点中的base64编码不是url安全的,它包括/和+而不是-和。因此,我发现生成此类令牌的最简单方法是 require('crypto').randomBytes(48, function(ex, buf) { token = buf.toString('base64').replace(/\//g,'_').replace(/\+/g,'-'); });
crypto.randomBytes
生成一个随机缓冲区。但是,节点中的base64编码不是url安全的,它包括/
和+
而不是-
和
。因此,我发现生成此类令牌的最简单方法是
require('crypto').randomBytes(48, function(ex, buf) {
token = buf.toString('base64').replace(/\//g,'_').replace(/\+/g,'-');
});
还有更优雅的方式吗?试试:
“十六进制”编码适用于节点v0.6.x或更新版本。如果您不是像我这样的JS专家,请选择同步选项。不得不花一些时间研究如何访问内联函数变量
var token = crypto.randomBytes(64).toString('hex');
一个小巧、安全、URL友好、唯一的JavaScript字符串ID生成器
描述如何使用URL安全性在base 64中编码。 您可以使用现有的库来完成这项工作 该职能将是:
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.
randomAsciiString(20);
// Returns 'rmRptK5niTSey7NlDk5y' which is 20 characters length.
randomString(20, 'ABCDEFG');
// Returns 'CCBAAGDGBBEGBDBECDCE' which is 20 characters length.
请注意,返回的字符串长度将与size参数(size!=final length)不匹配
注意,使用此解决方案生成的随机字符串不是均匀分布的 您还可以从有限的字符集生成强随机字符串,如下所示:
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');
}
从ES2016的角度来看,这更为正确。 ECMAScript 2016(ES7)方式 发电机/屈服方式 它有一个方法:)
随机URL和文件名字符串安全(1行)
Crypto.randomBytes(48).toString('base64')。replace(//\+/g,'-')。replace(//\//g,'.'''.')。replace(//\=/g,');
npm模块提供灵活的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()
生成随机数据。签出:
var crypto = require('crypto');
crypto.randomBytes(Math.ceil(length/2)).toString('hex').slice(0,length);
使用ES 2016 async and 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);
}
这在节点7中是现成的,没有任何Babel转换,使用async/await和
生成类似于
VjocVHdFiz5vGHnlnwqJKN0NdeHcz8eM
的简单函数,该函数为您获取URL安全且具有base64编码的令牌!这是上面两个答案的组合
const randomToken=()=>{
crypto.randomBytes(64).toString('base64').replace(//\//g,''''''.'替换(//\+/g,'-');
}
是一个很好的模块
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'
cryptoRandomString.async(选项)
add.async
如果你想得到一个承诺
那似乎更好,谢谢!“base64 url”编码很好,谢谢你的提示,但我认为OP只是想要已经标准的RFC3548第4节“使用url和文件名安全字母表的base64编码”。在我看来,替换字符是“足够优雅”的。如果你想把上面的代码作为bash-one的衬里,你可以做node-e”require('crypto')。randomBytes(48,function(ex,buf){console.log(buf.toString('hex'));“
而且你总是可以做buf.toString('base64'))
获取Base64编码的数字。Dmitry优秀的单行程序的更紧凑版本:node-p“require('crypto')。randomBytes(48)。toString('hex');“
(subbingBase64
forhex
)如果需要,代码的其余部分是什么?不需要了。你还想看到什么?Nevermind,我让它工作了,只是不确定你是如何把它扔进去的,但是更好地理解了“无耻的自我插件”的概念,我创建了另一个npm包:。您可以使用类似于正则表达式中字符类的范围语法指定允许的字符('a-zA-Z0-9.-'
)。这对于需要特定字符串长度的任何人来说都很方便。3/4用于处理基本转换/*返回长度为*/function randomString(length){return crypto.randomBytes(length*3/4).toString('base64');}的base64编码字符串,对于具有这些字符限制的数据库来说效果很好。@Jeffpowrs确实,Javascript正在升级:)查找承诺和生成器!try Wait,另一个ECMA7 promise Handler我认为您应该让ES 2016成为这方面的第一个例子,因为它正在朝着“正确的方式做”的方向发展。在大多数情况下,我在下面添加了一个针对节点的答案(使用require而不是import)。使用导入是否有特定的原因?您是否运行了babel?@real_ate确实如此,在正式支持导入之前,我已恢复使用CommonJS。@Lexynux解决方案1(使用URL和文件名安全字母表的Base 64编码),因为它是安全性方面最强的解决方案。此解决方案仅对密钥进行编码,不干扰密钥生产过程。感谢您的支持。您是否有任何可与社区分享的工作示例?它会受到欢迎吗?注意生成的随机字符串不是均匀分布的。一个简单的例子可以说明这一点,对于长度为255的字符集和长度为1的字符串,第一个字符出现的几率是原来的两倍。@Dodekeract是的,您正在讨论解决方案2。。这就是为什么解决方案1更强大的原因。我在回复中添加了nanoid第三方库,这是一个非常简单的答案!请注意,它可能会以一种不确定的方式暂停事件循环(只有在负载较重、时间敏感的系统中经常使用时才相关)。否则,请执行相同的操作,但使用异步版本的randomBytes。如果不希望所有内容都嵌套,请参见。谢谢虽然这确实有效,但请注意,在大多数情况下,您需要在JH的答案中演示异步选项。const generateToken=():Promise=>newpromise(解析)=
const id = anyid().encode('Aa0').bits(48 * 8).random().id();
// G4NtiI9OYbSgVl3EAkkoxHKyxBAWzcTI7aH13yIUNggIaNqPQoSS7SpcalIqX0qGZ
const id = anyid().encode('Aa').length(20).random().id();
// qgQBBtDwGMuFHXeoVLpt
var crypto = require('crypto');
crypto.randomBytes(Math.ceil(length/2)).toString('hex').slice(0,length);
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);
}
const crypto = require('crypto')
const randomBytes = Util.promisify(crypto.randomBytes)
const plain = (await randomBytes(24)).toString('base64').replace(/\W/g, '')
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'