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

require('crypto').randomBytes(48, function(ex, buf) {
    token = buf.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'

cryptoRandomString.async(options)如果你想获得一个承诺,添加.async。

其他回答

使用async/await和承诺。

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

生成类似于VjocVHdFiz5vGHnlnwqJKN0NdeHcz8eM的内容

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安全的情况下使用base64编码。 您可以使用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.

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

查看:

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

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

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