# 实现密码生成器的思路

- Link: https://www.ixiqin.com/2019/01/13/implement-password-generator-is-proposed/
- Published: 2019-01-13T15:40:40+08:00
- Author: 白宦成

在项目中有这样一个需求：需要生成一组随机密码，确保安全性。因此，我去翻了[一个项目](http://www.blazonry.com/javascript/password.php)
的代码。这里是具体的代码

    ```javascript
    function GeneratePassword() {
        if (parseInt(navigator.appVersion) <= 3) {
            alert("Sorry this only works in 4.0+ browsers");
            return true;
        }
        var length=8;
        var sPassword = "";
        length = document.aForm.charLen.options[document.aForm.charLen.selectedIndex].value;
        var noPunction = (document.aForm.punc.checked);
        var randomLength = (document.aForm.rLen.checked);
        if (randomLength) {
            length = Math.random();
            length = parseInt(length * 100);
            length = (length % 7) + 6
        }
        for (i=0; i < length; i++) {
            numI = getRandomNum();
            if (noPunction) { while (checkPunc(numI)) { numI = getRandomNum(); } }
            sPassword = sPassword + String.fromCharCode(numI);
        }
        document.aForm.passField.value = sPassword
        return true;
    }
    function getRandomNum() {
        // between 0 - 1
        var rndNum = Math.random()
        // rndNum from 0 - 1000
        rndNum = parseInt(rndNum * 1000);
        // rndNum from 33 - 127
        rndNum = (rndNum % 94) + 33;
        return rndNum;
    }
    function checkPunc(num) {
        if ((num >=33) && (num <=47)) { return true; }
        if ((num >=58) && (num <=64)) { return true; }
        if ((num >=91) && (num <=96)) { return true; }
        if ((num >=123) && (num <=126)) { return true; }
        return false;
    }

    Code language: JavaScript (javascript)
    ```

上完代码，接下来来分析一下这段代码

首先，这段代码中有三个函数，其关系如下图所示

![](https://files.ixiqin.com/2019/01/23091441/image.png?fit=1024%2C642&ssl=1)

密码生成器各函数关系图

其中 _getRandomNum_ 生成了一个范围在 33 – 127 的数字。这里是由于在后续生成随机字符
串时，用的是 _String.fromCharCode_，当数字在 33～127 之间时，能够确保生成的数字在
输入时比较简单。

![](https://files.ixiqin.com/2019/01/23091441/image-1.png)

String.fromCharCode 的测试结果

而 _checkPunc_ 则是检测输出的文字是否可以直接发音，这涉及到记忆的难度的问题，在一个
长的字符串中，记忆 ABCD 肯定比记忆逗号、破折号、句号等符号要简单一些，毕竟字母肯定
要好记忆点，可以自编语句来实现。

接下来我们来看最核心的 _GeneratorPassword_ 函数：如果将其中的 Dom 操作都忽略掉，
并设置一个值。并进行配置后，代码如下：

    ```javascript
    function GeneratePassword() {
        // 检测浏览器支持
        if (parseInt(navigator.appVersion) <= 3) {
            alert("Sorry this only works in 4.0+ browsers");
            return true;
        }
        var length=8;
        var sPassword = "";
        length = 10 // 此处代码原为使用 dom 函数获取表单数据的代码，来实现自定义长度的功能。
        var noPunction = false// 此处代码原为获取表单数据的代码，控制是否检测密码的可读性
        var randomLength = false // 此处代码原为获取表单数据的代码，控制是否使用随机长度。
        // 如果使用随机长度的密码，则进入循环
        if (randomLength) {
            length = Math.random();
            length = parseInt(length * 100); // 生成 0 ~ 100 之间的数字
            length = (length % 7) + 6 // 对生成的长度取余，则最短为6，最长为12
        }
        // 根据长度进行循环
        for (i=0; i < length; i++) {
            numI = getRandomNum();  // 获取一个随机数
            if (noPunction) { while (checkPunc(numI)) { numI = getRandomNum(); } } // 如果需要判断发音，进行发音判断，判断失败就重新生成，直到成功。
            sPassword = sPassword + String.fromCharCode(numI); // 将生成的字符串加入到原有的字符串最后
        }
        // 设置代码到 Dom 元素中
        return true;
    }
    Code language: JavaScript (javascript)
    ```

其代码逻辑图如下

![](https://files.ixiqin.com/2019/01/23091441/未命名表单-1.png)

密码生成器的代码逻辑图
