使用javascript中的要求生成随机密码字符串

fff*_*f01 79 javascript

我想生成一个随机字符串,必须有来自az和3个数字的5个字母.

我怎么能用javascript做到这一点?

我有以下脚本,但它不符合我的要求.

        var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
        var string_length = 8;
        var randomstring = '';
        for (var i=0; i<string_length; i++) {
            var rnum = Math.floor(Math.random() * chars.length);
            randomstring += chars.substring(rnum,rnum+1);
        }
Run Code Online (Sandbox Code Playgroud)

Rob*_*b W 285

强制使用固定数量的字符是一个主意.它不会提高密码的质量.更糟糕的是,它减少了可能的密码数量,因此通过强制进行黑客攻击变得更容易.

要生成由字母数字字符组成的随机单词,请使用:

var randomstring = Math.random().toString(36).slice(-8);
Run Code Online (Sandbox Code Playgroud)

它是如何工作的?

Math.random()                        // Generate random number, eg: 0.123456
             .toString(36)           // Convert  to base-36 : "0.4fzyo82mvyr"
                          .slice(-8);// Cut off last 8 characters : "yo82mvyr"
Run Code Online (Sandbox Code Playgroud)

Number.prototype.toStringstring.prototype.slice方法的文档.

  • 请勿使用:由于数字从二进制转换为十进制,并且没有足够的位来"填满"整数十进制空格,因此最后一位数将仅从某组值中选择.例如,在我的计算机上,最后一位数字只是"i","r"和"9".请改用:`Math.random().toString(36).substr(2,8)` (32认同)
  • 我同意,但有时你不能决定;) (6认同)
  • 我想提一下,这种方法会产生大量重复.生成的1.000`密码的1%是重复的,'10.000`为10%,100.000`为57%,而1.000.000为超过95%.**[见此测试](http://jsfiddle.net/zessx/ARf5S/)** (3认同)
  • 解释 36 的作用:来自 [mozilla](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toString) _toString() 方法解析它的第一个参数,然后尝试以指定的基数(基数)返回字符串表示形式。对于10以上的基数,字母表中的字母表示大于9的数字。例如,对于十六进制数(基数为16),使用a到f。_所以据此,使用基数36,我们在0-9之后得到az . (2认同)
  • @ShishirGupta` .toString`只接受一个基数,包括36个.这个答案是作为非加密随机字符串的单行.如果你想拥有大写字母,可以使用`Math.random`(或`crypto.getRandomValues`,如果有的话)并将结果映射到az,AZ,0-9.例如,使用saaj的答案如下. (2认同)
  • 不知道这如何解决 OP 要求 ***“az 中的 5 个字母和 3 个数字”***。我明白了,作者认为这是一个坏主意......但它仍然是要求 (2认同)

saa*_*aaj 36

更加可维护和安全的方法.

var Password = {
 
  _pattern : /[a-zA-Z0-9_\-\+\.]/,
  
  
  _getRandomByte : function()
  {
    // http://caniuse.com/#feat=getrandomvalues
    if(window.crypto && window.crypto.getRandomValues) 
    {
      var result = new Uint8Array(1);
      window.crypto.getRandomValues(result);
      return result[0];
    }
    else if(window.msCrypto && window.msCrypto.getRandomValues) 
    {
      var result = new Uint8Array(1);
      window.msCrypto.getRandomValues(result);
      return result[0];
    }
    else
    {
      return Math.floor(Math.random() * 256);
    }
  },
  
  generate : function(length)
  {
    return Array.apply(null, {'length': length})
      .map(function()
      {
        var result;
        while(true) 
        {
          result = String.fromCharCode(this._getRandomByte());
          if(this._pattern.test(result))
          {
            return result;
          }
        }        
      }, this)
      .join('');  
  }    
    
};
Run Code Online (Sandbox Code Playgroud)
<input type='text' id='p'/><br/>
<input type='button' value ='generate' onclick='document.getElementById("p").value = Password.generate(16)'>
Run Code Online (Sandbox Code Playgroud)

  • 除了只能在浏览器中使用。 (2认同)

mwa*_*wag 22

许多答案(包括本文的原文)都没有解决OP的字母和数字计数要求.以下是两种解决方案:一般(无最小字母/数字)和规则.

一般:

我相信这是比上述更好的一般解决方案,因为:

  • 它比接受/最高投票的答案更安全,也更通用,因为它以区分大小写的方式支持任何字符集
  • 它比其他答案更简洁(一般解决方案,最多3行;可以是单行)
  • 它只使用原生Javascript-无需安装或其他库

注意

  • 这对IE浏览器,在Array.fill()原型必须polyfilled
  • 如果可用,最好使用window.crypto.getRandomValues()而不是Math.random()(感谢@BenjaminH指出)

三内胆:

var pwdChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
var pwdLen = 10;
var randPassword = Array(pwdLen).fill(pwdChars).map(function(x) { return x[Math.floor(Math.random() * x.length)] }).join('');
Run Code Online (Sandbox Code Playgroud)

或者,作为一个班轮:

var randPassword = Array(10).fill("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz").map(function(x) { return x[Math.floor(Math.random() * x.length)] }).join('');
Run Code Online (Sandbox Code Playgroud)

带字母/数字规则

现在,上面的变化.这将从给定的字符集生成三个随机字符串(字母,数字,或者),然后对结果进行加扰.

请注意,以下使用sort()仅用于说明目的.对于生产用途,请使用诸如Durstenfeld之类的shuffle函数替换下面的sort()函数.

首先,作为一个功能:

function randPassword(letters, numbers, either) {
  var chars = [
   "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", // letters
   "0123456789", // numbers
   "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" // either
  ];

  return [letters, numbers, either].map(function(len, i) {
    return Array(len).fill(chars[i]).map(function(x) {
      return x[Math.floor(Math.random() * x.length)];
    }).join('');
  }).concat().join('').split('').sort(function(){
    return 0.5-Math.random();
  }).join('')
}

// invoke like so: randPassword(5,3,2);
Run Code Online (Sandbox Code Playgroud)

同样的事情,作为一个2线程(诚然,非常长和丑陋的线 - 如果你使用适当的随机播放功能将不会是1线.不推荐,但有时它很有趣):

var chars = ["ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz","0123456789", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"];
var randPwd = [5,3,2].map(function(len, i) { return Array(len).fill(chars[i]).map(function(x) { return x[Math.floor(Math.random() * x.length)] }).join('') }).concat().join('').split('').sort(function(){return 0.5-Math.random()}).join('');
Run Code Online (Sandbox Code Playgroud)

  • Math.random() 的使用也是可以预测的。因此,为了生成密码,最好使用像 window.crypto.getRandomValues 这样的函数。 (2认同)
  • 它更安全的原因是它支持输出中可能的字符数比使用 toString(36) 多。使用固定的输出长度(例如 8 个),如果您最多有 36 个字符可供选择,那么您的排列比有 62 个字符(如示例中)或更好的是,整个 95 个可打印字符(ascii ) 字符,或者如果使用 unicode,则每个字节的可能性甚至更高。 (2认同)

小智 9

使用 Math.random() 生成的任何密码都是极其糟糕的

该函数使用系统时间作为随机数生成器的种子。任何知道密码生成时间的人都可以轻松暴力破解密码。

在几乎所有情况下,这些数据都很容易获得 - 只需获取被黑数据库中的 Registration_time 列,并使用 15 到 0 分钟之前的时间测试 Math.random() 算法生成的所有值。

使用 Math.random() 生成的密码完全没有价值,因为密码第一次使用的时间足以破解它。


Ale*_*ger 8

这不是完全优化的,但它应该工作.

var chars = "ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
var string_length = 8;
var randomstring = '';
var charCount = 0;
var numCount = 0;

for (var i=0; i<string_length; i++) {
    // If random bit is 0, there are less than 3 digits already saved, and there are not already 5 characters saved, generate a numeric value. 
    if((Math.floor(Math.random() * 2) == 0) && numCount < 3 || charCount >= 5) {
        var rnum = Math.floor(Math.random() * 10);
        randomstring += rnum;
        numCount += 1;
    } else {
        // If any of the above criteria fail, go ahead and generate an alpha character from the chars string
        var rnum = Math.floor(Math.random() * chars.length);
        randomstring += chars.substring(rnum,rnum+1);
        charCount += 1;
    }
}

alert(randomstring);
Run Code Online (Sandbox Code Playgroud)

​ ​ ​

这是一个jsfiddle供您测试:http://jsfiddle.net/sJGW4/3/


din*_*sky 8

正如@RobW 指出的那样,将密码限制为 OP 方案中提出的固定数量的字符是一个坏主意。但更糟糕的是,提出基于代码的答案是Math.random一个非常糟糕的主意

让我们从坏主意开始。OP 代码从一组 62 个字符中随机选择一个包含 8 个字符的字符串。将随机字符串限制为 5 个字母和 3 个数字意味着生成的密码最多将具有28.5 位的熵(与 47.6 位的潜力相反)如果取消了 5 个字母和 3 个数字的分配限制)。那不是很好。但实际上,情况更糟。所述充其量代码的方面是通过使用破坏Math.random作为密码产生熵的手段。Math.random是一个伪随机数生成器。由于伪随机数生成器的确定性,生成的密码的熵非常糟糕,使任何此类提议的解决方案都成为一个非常糟糕的主意。假设这些密码被分发给最终用户(o/w 有什么意义),收到这样的密码的活跃对手很有可能预测未来分发给其他用户的密码,这可能不是一件好事。

但回到刚才的坏主意。假设使用密码强的伪随机数生成器而不是Math.random。为什么要将密码限制为 28.5 位?如前所述,这不是很好。想必5个字母3个数字的方案是为了帮助用户管理随机分发的密码。但是让我们面对它,你必须平衡易用性使用的价值和熵的28.5位不是针对主动攻击防御多少价值。

但坏事已经够多了。让我们提出一条前进的道路。我将使用 JavaScript EntropyString库,它“有效地从各种字符集生成指定熵的加密强随机字符串”。而不是 OP 62 个字符,我将使用一个包含 32 个字符的字符集,以减少使用容易混淆的字符或英文单词的形成。而不是 5 个字母、3 个数字方案(它的熵太少),我将宣布密码将具有 60 位的熵(这是易用性与价值的平衡)。

import { Entropy, charSet32 } from 'entropy-string'
const random = new Entropy({ bits: 60, charset: charset32 })
const string = random.string()
Run Code Online (Sandbox Code Playgroud)

“Q7LfR8Jn7RDp”

请注意Entropy指定所需熵位的参数,而不是更常见的随机字符串生成解决方案,该解决方案指定传入字符串长度(这既被误导又通常未指定,但这是另一回事)。


小智 6

我写了一个小答案,灵感来自你的答案:

(function(){g=function(){c='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';p='';for(i=0;i<8;i++){p+=c.charAt(Math.floor(Math.random()*62));}return p;};p=g();while(!/[A-Z]/.test(p)||!/[0-9]/.test(p)||!/[a-z]/.test(p)){p=g();}return p;})()
Run Code Online (Sandbox Code Playgroud)

此函数返回密码,可以在bookmarklet中使用,如:

javascript:alert(TheCodeOfTheFunction);
Run Code Online (Sandbox Code Playgroud)


Rya*_*ton 6

如果您需要使用至少1个数字,1个大写字母和1个小写字母生成的密码:

function generatePassword(passwordLength) {
  var numberChars = "0123456789";
  var upperChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  var lowerChars = "abcdefghijklmnopqrstuvwxyz";
  var allChars = numberChars + upperChars + lowerChars;
  var randPasswordArray = Array(passwordLength);
  randPasswordArray[0] = numberChars;
  randPasswordArray[1] = upperChars;
  randPasswordArray[2] = lowerChars;
  randPasswordArray = randPasswordArray.fill(allChars, 3);
  return shuffleArray(randPasswordArray.map(function(x) { return x[Math.floor(Math.random() * x.length)] })).join('');
}

function shuffleArray(array) {
  for (var i = array.length - 1; i > 0; i--) {
    var j = Math.floor(Math.random() * (i + 1));
    var temp = array[i];
    array[i] = array[j];
    array[j] = temp;
  }
  return array;
}

alert(generatePassword(12));
Run Code Online (Sandbox Code Playgroud)

如果您想玩/测试,这里是小提琴:http : //jsfiddle.net/sJGW4/155/

推荐给@mwag,让我开始创建它。

  • 你缺少小写的“j”:P 否则,这里有好东西。不过稍微修改了一下以满足我的要求。 (2认同)

Nin*_*ham 6

对于正在寻找最简单脚本的人.不while (true),不if/else,没有声明.

基于mwag的答案,但这个使用crypto.getRandomValues,比一个更强的随机Math.random.

Array(20)
  .fill('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz~!@-#$')
  .map(x => x[Math.floor(crypto.getRandomValues(new Uint32Array(1))[0] / (0xffffffff + 1) * x.length)])
  .join('');
Run Code Online (Sandbox Code Playgroud)

看到这个神奇的魔力0xffffffff.


打开控制台并自己测试:

for (let i = 0 ; i < 100; i++)
  console.log(
    Array(20)
    .fill('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz~!@-#$')
    .map(x => x[Math.floor(crypto.getRandomValues(new Uint32Array(1))[0] / (0xffffffff + 1) * x.length)])
    .join('')
  )
Run Code Online (Sandbox Code Playgroud)

如果考虑性能,可以试试这个:

var generate = (
  length = 20,
  wishlist = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz~!@-#$"
) => Array(length)
      .fill('') // fill an empty will reduce memory usage
      .map(() => wishlist[Math.floor(crypto.getRandomValues(new Uint32Array(1))[0] / (0xffffffff + 1) * wishlist.length)])
      .join('');

// Generate 100 passwords
for (var i = 0; i < 100; i++) console.log(generate());
Run Code Online (Sandbox Code Playgroud)

  • 这会产生均匀性问题。Nanoid 文档 https://github.com/ai/nanoid 中提到,随机 % 字母表是编码 ID 生成器时常见的错误。分布不会均匀;与其他符号相比,某些符号出现的机会会较低。 (5认同)
  • @ Gnuogh 这是生成密码的简单解决方案。如果开发人员想要更安全,他们应该使用经过测试的软件包。那里有很多软件包,不仅仅是您尝试广告的 Nano。nano 也做了类似的随机操作,但对随机字符做了一些步骤,没有留下深刻的印象。它可用于生成 id,而不是密码。 (3认同)
  • 有用且简单的解决方案。任何想要在 NodeJS 中执行此操作的人都可以简单地将 `crypto.getRandomValues` 替换为 [crypto.randomFillSync](https://nodejs.org/docs/latest/api/crypto.html#crypto_crypto_randomfillsync_buffer_offset_size)。 (2认同)
  • 对于Python版本,更简单的解决方案是使用Python内置的secrets模块;`secrets.token_urlsafe(length)` /sf/answers/4302985991/ (2认同)

Rub*_*ous 5

我对这个问题的基于加密的看法。使用 ES6 并省略任何浏览器功能检查。对安全性或性能有何评论?

const generatePassword = (
  passwordLength = 12,
  passwordChars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
) =>
  [...window.crypto.getRandomValues(new Uint32Array(passwordLength))]
    .map(x => passwordChars[x % passwordChars.length])
    .join('');
Run Code Online (Sandbox Code Playgroud)

  • 使用“%”[在分布中引入偏差](https://dimitri.xyz/random-ints-from-random-bits/) (2认同)

归档时间:

查看次数:

89057 次

最近记录:

6 年,2 月 前