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

在中,Erik需要在Node.js中生成一个安全的随机令牌。有一种方法
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');
  • 使用nanoid第三方库[NEW!]

  • 一个小巧、安全、URL友好、唯一的JavaScript字符串ID生成器


  • 使用URL和文件名安全字母表的Base 64编码

  • 描述如何使用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');“
    (subbing
    Base64
    for
    hex
    )如果需要,代码的其余部分是什么?不需要了。你还想看到什么?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'