Javascript Node.js 中的安全随机令牌

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8855687/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 07:48:30  来源:igfitidea点击:

Secure random token in Node.js

javascriptnode.jsbase64securestring

提问by Hubert OG

In this questionErik needs to generate a secure random token in Node.js. There's the method crypto.randomBytesthat generates a random Buffer. However, the base64 encoding in node is not url-safe, it includes /and +instead of -and _. Therefore, the easiest way to generate such token I've found is

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

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

Is there a more elegant way?

有没有更优雅的方式?

回答by thejh

Try crypto.randomBytes():

尝试crypto.randomBytes()

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

The 'hex' encoding works in node v0.6.x or newer.

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

回答by phoenix2010

Synchronous option in-case if you are not a JS expert like me. Had to spend some time on how to access the inline function variable

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

var token = crypto.randomBytes(64).toString('hex');

回答by Yves M.

0. Using nanoid third party library [NEW!]

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

A tiny, secure, URL-friendly, unique string ID generator for JavaScript

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

https://github.com/ai/nanoid

https://github.com/ai/nanoid

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



1. Base 64 Encoding with URL and Filename Safe Alphabet

1. 带有 URL 和文件名安全字母表的 Base 64 编码

Page 7 of RCF 4648describes how to encode in base 64 with URL safety. You can use an existing library like base64urlto do the job.

RCF 4648 的第 7 页描述了如何在具有 URL 安全性的 base 64 中进行编码。您可以使用像base64url这样的现有库来完成这项工作。

The function will be:

该功能将是:

var crypto = require('crypto');
var base64url = require('base64url');

/** Sync */
function randomStringAsBase64Url(size) {
  return base64url(crypto.randomBytes(size));
}

Usage example:

用法示例:

randomStringAsBase64Url(20);
// Returns 'AXSGpLVjne_f7w5Xg-fWdoBwbfs' which is 27 characters length.

Note that the returned string length will not match with the size argument (size != final length).

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



2. Crypto random values from limited set of characters

2. 来自有限字符集的加密随机值

Beware that with this solution the generated random string is not uniformly distributed.

请注意,使用此解决方案生成的随机字符串不是均匀分布的。

You can also build a strong random string from a limited set of characters like that:

您还可以从一组有限的字符中构建一个强大的随机字符串,如下所示:

var crypto = require('crypto');

/** Sync */
function randomString(length, chars) {
  if (!chars) {
    throw new Error('Argument \'chars\' is undefined');
  }

  var charsLength = chars.length;
  if (charsLength > 256) {
    throw new Error('Argument \'chars\' should not have more than 256 characters'
      + ', otherwise unpredictability will be broken');
  }

  var randomBytes = crypto.randomBytes(length);
  var result = new Array(length);

  var cursor = 0;
  for (var i = 0; i < length; i++) {
    cursor += randomBytes[i];
    result[i] = chars[cursor % charsLength];
  }

  return result.join('');
}

/** Sync */
function randomAsciiString(length) {
  return randomString(length,
    'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789');
}

Usage example:

用法示例:

randomAsciiString(20);
// Returns 'rmRptK5niTSey7NlDk5y' which is 20 characters length.

randomString(20, 'ABCDEFG');
// Returns 'CCBAAGDGBBEGBDBECDCE' which is 20 characters length.

回答by real_ate

The up-to-date right wayto do this asynchronously using ES 2016 standards of async and await (as of Node 7) would be the following:

使用 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);
}

This works out of the box in Node 7 without any Babel transformations

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

回答by Kedem

Random URL and filename string safe (1 liner)

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

Crypto.randomBytes(48).toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/\=/g, '');

回答by Znarkus

With async/await and promisification.

使用 async/await 和promisification

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

Generates something similar to VjocVHdFiz5vGHnlnwqJKN0NdeHcz8eM

产生类似的东西 VjocVHdFiz5vGHnlnwqJKN0NdeHcz8eM

回答by sudam

Check out:

查看:

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

回答by Karl Morrison

Look at real_atesES2016 way, it's more correct.

看看real_atesES2016 的方式,更正确。

ECMAScript 2016 (ES7) way

import crypto from 'crypto';

function spawnTokenBuf() {
    return function(callback) {
        crypto.randomBytes(48, callback);
    };
}

async function() {
    console.log((await spawnTokenBuf()).toString('base64'));
};

ECMAScript 2016 (ES7) 方式

import crypto from 'crypto';

function spawnTokenBuf() {
    return function(callback) {
        crypto.randomBytes(48, callback);
    };
}

async function() {
    console.log((await spawnTokenBuf()).toString('base64'));
};

Generator/Yield Way

发电机/屈服方式

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

回答by aleung

The npm module anyidprovides flexible API to generate various kinds of string ID / code.

npm 模块anyid提供了灵活的 API 来生成各种字符串 ID/代码。

To generate random string in A-Za-z0-9 using 48 random bytes:

使用 48 个随机字节在 A-Za-z0-9 中生成随机字符串:

const id = anyid().encode('Aa0').bits(48 * 8).random().id();
// G4NtiI9OYbSgVl3EAkkoxHKyxBAWzcTI7aH13yIUNggIaNqPQoSS7SpcalIqX0qGZ

To generate fixed length alphabet only string filled by random bytes:

要生成由随机字节填充的仅固定长度字母的字符串:

const id = anyid().encode('Aa').length(20).random().id();
// qgQBBtDwGMuFHXeoVLpt

Internally it uses crypto.randomBytes()to generate random.

在内部,它用于crypto.randomBytes()生成随机数。

回答by jsonmaur

https://www.npmjs.com/package/crypto-extrahas a method for it :)

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

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