329

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

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

有没有更优雅的方式?

4

14 回答 14

427

尝试crypto.randomBytes()

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

“十六进制”编码适用于节点 v0.6.x 或更高版本。

于 2012-01-13T19:33:12.227 回答
289

如果您不是像我这样的 JS 专家,可以选择同步选项。不得不花一些时间在如何访问内联函数变量上

var token = crypto.randomBytes(64).toString('hex');
于 2014-08-13T16:59:27.257 回答
102

1. 使用 nanoid 第三方库 [新!]


用于 JavaScript 的小型、安全、URL 友好、唯一的字符串 ID 生成器

https://github.com/ai/nanoid

import { nanoid } from "nanoid";
const id = nanoid(48);

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


RCF 4648 的第 7 页描述了如何在具有 URL 安全性的 base 64 中进行编码。您可以使用像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.

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


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.
于 2014-09-05T17:04:28.627 回答
21

使用 ES 2016 异步和等待标准(从节点 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);
}

这在 Node 7 中开箱即用,无需任何 Babel 转换

于 2017-05-09T10:10:44.383 回答
12

随机 URL 和文件名字符串安全(1 行)

Crypto.randomBytes(48).toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/\=/g, '');
于 2016-03-15T10:34:22.590 回答
10

使用 async/await 和promisification

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

生成类似于VjocVHdFiz5vGHnlnwqJKN0NdeHcz8eM

于 2017-07-31T12:49:26.633 回答
8

查看:

var crypto = require('crypto');
crypto.randomBytes(Math.ceil(length/2)).toString('hex').slice(0,length);
于 2017-01-21T19:35:31.560 回答
4

real_atesES2016的方式,更正确。

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'));
});
于 2015-05-28T05:19:35.287 回答
3

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

var value = crypto.random(/* desired length */)
于 2016-02-19T23:54:45.650 回答
3

npm 模块anyid提供灵活的 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()生成随机数。

于 2016-08-05T05:39:22.247 回答
2

一个简单的函数,为您提供一个 URL 安全且具有 base64 编码的令牌!这是上面2个答案的组合。

const randomToken = () => {
    crypto.randomBytes(64).toString('base64').replace(/\//g,'_').replace(/\+/g,'-');
}
于 2020-01-13T18:29:11.863 回答
2

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您想获得promise.

于 2020-10-31T06:12:12.697 回答
2

从 Node.js 14.18 和 15.7 开始,内置了url-safe base64 编码支持:

const token = crypto.randomBytes(48).toString('base64url');

如果你想使用异步版本(因为函数可能必须等待熵),它可以被承诺更好地与现代模式保持一致:

const randomBytesAsync = util.promisify(crypto.randomBytes);

const token = (await randomBytesAsync(48)).toString('base64url');
于 2021-12-12T01:28:44.583 回答
0

您可以使用random-token lib。它很容易使用。:)

var randomToken = require('random-token').create('abcdefghijklmnopqrstuvwxzyABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789');
var token = randomToken(16);

而且你不能使用不同的盐

var randomToken = require('random-token');
var token = randomToken(16); // output -> d8d4kd29c40f021 ```
于 2021-11-07T17:15:50.347 回答