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

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

还有更优雅的方式吗?


当前回答

查看:

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

其他回答

尝试crypto.randomBytes ():

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

'hex'编码在节点v0.6中工作。X或更新版本。

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.

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

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

使用async/await和承诺。

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

生成类似于VjocVHdFiz5vGHnlnwqJKN0NdeHcz8eM的内容

使用ES 2016标准的async和await(截至Node 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转换