1

このjavascriptパスワード生成機能があります。現在、選択した仕様に一致しないパスワードを破棄しています。たとえば、パスワードに数字が含まれていない場合は、それを破棄して、数字が含まれる新しいパスワードを生成します。ただし、これは効率的なパフォーマンス万力ではないようです。少なくとも私にはそうではありません。

生成されたパスワードに特定の文字を強制的に実装するより良い方法はありますか?

また、パスワードに特殊文字を強制的に含めることができるように追加する予定です。これを現在の方法で行うと、パスワードに特殊文字が含まれているかどうかを確認し、そうでない場合はそれをスローするために正規表現が必要になります(これもあまり効率的ではないようです)。

function generatePassword(length, charset, nosimilar) {
    // default parameters
    length = (typeof length === "undefined") ? 8 : length;
    charset = (typeof charset === "undefined") ? 'abcdefghjknpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ123456789' : charset;
    nosimilar = (typeof similar === "undefined") ? true : nosimilar;

    var gen;
    retVal = "";
    for (var i = 0, n = charset.length; i < length; ++i) {
        gen = charset.charAt(Math.floor(Math.random() * n))
        if ( (retVal.charAt( retVal.length-1 ) == gen) && (nosimilar)) {
            retVal = retVal.substring(0, retVal.length - 1)
            retVal += charset.charAt(Math.floor(Math.random() * n))
            console.log('Generated character same as the last one. Trunkated and regenerated.');
        }
        retVal += gen;
    }

    // if charset contains numbers make sure we get atleast one number
    if ( (retVal.match(/\d+/g) == null) && (charset.match(/\d+/g) != null)) {
    console.log('Password generated but no numbers found. Regenerating.');
    generatePassword(length, charset, nosimilar);
    }

    return retVal;
}

if ($("#chLetters").prop('checked')) charset += 'abcdefghjknpqrstuvwxyz';
if ($("#chNumbers").prop('checked')) charset += '123456789';
if ($("#chMixedCase").prop('checked')) charset += 'ABCDEFGHJKLMNPQRSTUVWXYZ';
if ($("#chSpecial").prop('checked')) charset += '!@$%&?+*-_';

$("#passgen").text(generatePassword($("#maxLength").val(), charset, $("#chNoSimilar").prop('checked')));
4

3 に答える 3

1

n 文字の長さのパスワードがあり、少なくとも 1 つの文字、1 つの数字、および 1 つの特殊文字が必要である場合、それぞれの文字が 1 ~ n-2 文字であることを意味します。例(簡略化):

function generatePassword( length ) {
    var letters = 'abcdefghjknpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ',
        special = '{}()#%&',
        characters = [],
        amountOfLetters = Math.floor( Math.random() * ( length - 2 ) ) + 1,
        amountOfNumbers = Math.floor( Math.random() * ( length - 1 - amountOfLetters ) ) + 1,
        amountOfSpecial = length - ( amountOfLetters + amountOfNumbers );

    // pick letters
    for (var i = 0, n = letters.length; i < amountOfLetters; ++i) {
        characters.push( letters.charAt( Math.floor( Math.random() * n ) ) );
    }

    // pick numbers
    for ( i = 0; i < amountOfNumbers; ++i) {
        characters.push( ''+( Math.floor( Math.random() * 9 ) + 1 ) );
    }

    // pick special characters
    for ( i = 0, n = special.length; i < amountOfSpecial; ++i) {
        characters.push( special.charAt( Math.floor( Math.random() * n ) ) );
    }

    // sort the array and concatenate elements into a string
    return characters.sort( function( a, b ) {
        return Math.random() - 0.5;
    } ).join( '' );
}

デモ: http://jsfiddle.net/gGwyM/

この関数は、1 から n-2 文字の間で選択し、次に 1 から nL-1 の間の数字 (L は文字数) を選択し、残りは特殊文字です。これにより、パスワードに各グループの少なくとも 1 文字が含まれることが保証されます。

(配列をランダム化するには、ここにあるものよりも優れた関数を使用する必要があることに注意してください。たとえば、JavaScript 配列をランダム化 (シャッフル) する方法を参照してください) 。

于 2013-05-04T09:36:41.923 に答える
0

このようなものを使用できます。このメソッドを使用すると、複数のキー セットを作成できます。単純なオプション属性を使用することで、長さを設定したり、16 進数のパスワードを生成することを選択したりして、これらのキーセットをパスワード生成の内外に切り替えることができます。

function isObject(value) {
  return Object.prototype.toString.call(value) === '[object Object]';
}

function assign(target, source) {
  for (var prop in source) {
    if (source.hasOwnProperty(prop)) {
      target[prop] = source[prop];
    }
  }

  return target;
}

function shuffle(obj) {
  var i = obj.length;
  var rnd, tmp;

  while (i) {
    rnd = Math.floor(Math.random() * i);
    i -= 1;
    tmp = obj[i];
    obj[i] = obj[rnd];
    obj[rnd] = tmp;
  }

  return obj;
}

function generatePassword(options) {
  var opts = isObject(options) ? assign({}, options) : {};
  var keyspace = '';
  if (opts.hex) {
    keyspace = '0123456789abcdef';
    if (opts.uppercase) {
      keyspace = keyspace.toUpperCase();
    }
  } else {
    if (opts.alpha) {
      keyspace += 'abcdefghijklmnopqrstuvwxyz';
    }

    if (opts.uppercase) {
      keyspace += 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
    }

    if (opts.numeric) {
      keyspace += '0123456789';
    }

    if (opts.punctuation) {
      keyspace += "`!\"?$?%^&*()_-+={[}]:;@'~#|\\<,>.?/";
    }
  }

  if (keyspace.length - 1 < 0) {
    return '';
  }

  opts.size = opts.size >>> 0 || 16;
  if (opts.size < 5) {
    opts.size = 5;
  } else if (opts.size > 100) {
    opts.size = 100;
  }

  return shuffle(keyspace.split('')).join('').slice(0, opts.size);
}

var password = generatePassword({
  alpha: true,
  uppercase: true,
  numeric: true,
  punctuation: true
});

console.log(password);

他のオプションは、長さのサイズの16進生成です

使用したい特殊文字の文字列を取るように変更できます。

更新:これは、選択した文字の各タイプの数を強制し、上記の単純な例と同様に機能する、より複雑な例です。

function isObject(value) {
  return Object.prototype.toString.call(value) === '[object Object]';
}

function assign(target, source) {
  for (var prop in source) {
    if (source.hasOwnProperty(prop)) {
      target[prop] = source[prop];
    }
  }

  return target;
}

function shuffle(obj) {
  var i = obj.length;
  var rnd, tmp;

  while (i) {
    rnd = Math.floor(Math.random() * i);
    i -= 1;
    tmp = obj[i];
    obj[i] = obj[rnd];
    obj[rnd] = tmp;
  }

  return obj;
}

function getXChars(string, number) {
  var str = typeof string === 'string' ? string : '';
  var num = typeof number === 'number' && number > 0 ? number : 0;
  var array = [];
  var i = str.length;
  var rnd;

  while (i && array.length < num) {
    rnd = Math.floor(Math.random() * i);
    i -= 1;
    array.push(str.charAt(rnd));
  }

  return array;
}

function generatePassword(opts) {
  var opts = isObject(opts) ? assign({}, opts) : {};
  var keyspace = '';
  var result = [];
  var i = 0;
  var tmp;

  if (typeof opts.hex === 'number' && opts.hex > 0) {
    i += opts.hex;
    keyspace = '0123456789abcdef';
    if (opts.uppercase === true) {
      keyspace = keyspace.toUpperCase();
    }

    result = result.concat(getXChars(keyspace, opts.hex));
  } else {
    if (typeof opts.alpha === 'number' && opts.alpha > 0) {
      i += opts.alpha;
      tmp = 'abcdefghijklmnopqrstuvwxyz';
      keyspace += tmp;
      result = result.concat(getXChars(tmp, opts.alpha));
    }

    if (typeof opts.uppercase === 'number' && opts.uppercase > 0) {
      i += opts.uppercase;
      tmp = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
      keyspace += tmp;
      result = result.concat(getXChars(tmp, opts.uppercase));
    }

    if (typeof opts.numeric === 'number' && opts.numeric > 0) {
      i += opts.numeric;
      tmp = '0123456789';
      keyspace += tmp;
      result = result.concat(getXChars(tmp, opts.numeric));
    }

    if (typeof opts.punctuation === 'number' && opts.punctuation > 0) {
      i += opts.punctuation;
      tmp = "`!\"?$?%^&*()_-+={[}]:;@'~#|\\<,>.?/";
      keyspace += tmp;
      result = result.concat(getXChars(tmp, opts.punctuation));
    }
  }

  if (keyspace.length === 0) {
    return keyspace;
  }

  opts.size = opts.size >>> 0 || 16;
  if (opts.size < 5) {
    opts.size = 5;
  } else if (opts.size > 100) {
    opts.size = 100;
  }

  result = result.concat(getXChars(keyspace, opts.size - i));

  return shuffle(result).join('');
}

var password = generatePassword({
  alpha: 1,
  uppercase: 1,
  numeric: 1,
  punctuation: 1
});

console.log(password);

更新: ここで約束されているように、Math.randomの可能な代替品です。window.crypto.getRandomValuesが利用可能な場合はそれを使用し、そうでない場合は Math.random にフォールバックします。

function random() {
  if (window.crypto && typeof window.crypto.getRandomValues === 'function') {
    console.log('Using crypto');
    var array = new Uint32Array(1);
    window.crypto.getRandomValues(array);
    return array[0] / (Math.pow(2, 32) + 1);
  }

  console.log('Using random');
  return Math.random();
}

console.log(random());

于 2013-05-04T09:29:14.157 に答える