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

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

还有更优雅的方式吗?


当前回答

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

其他回答

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

Const random = size => String.fromCharCode ( …crypto.getRandomValues ( 新Uint8Array(大小) ) ) ).replaceAll(“+”,“x”)。replaceAll(“/”,“我”)。片(0,大小) For(令I = 5;我——;)console.log(随机(16))

所有doe我只会使用一个uint8array \w预定义的长度,并称为crypto。getRandomValues每当我需要一些uniq(和切片如果我必须),从来不处理字符串或base64, base64只是不必要的开销。 (为fast分配大量缓冲区的成本很高)

const buf256 = new Uint8Array(256)
const random = crypto.getRandomValues.bind(crypto, buf256)

for (let i = 5; i--;) random()//.slice()

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。

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 -e "console.log(crypto.randomBytes(48).toString('hex'))"

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

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