我有这个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')));
答案 0 :(得分:1)
如果您的密码长度为n个字符,并且要求它至少包含一个字母,一个数字和一个特殊字符,则表示每个密码的字符数为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( '' );
}
该功能选择1到n-2个字母,然后是1到n-L-1个数字(其中L是字母数量),其余为特殊字符。这可以保证密码至少包含每个组中的一个字符。
(请注意,你应该使用比我这里更好的函数来随机化数组,参见例如How to randomize (shuffle) a JavaScript array?)
答案 1 :(得分:0)
你可以使用这样的东西。使用此方法可以创建多个密钥集,并且通过使用简单的选项属性,您可以将这些密钥集切换进出密码生成,同时设置长度甚至选择生成十六进制密码。
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);
其他选项是十六进制生成长度的大小
您可以修改它以获取您想要使用的特殊字符串。
更新:这是一个更复杂的示例,它强制执行各种类型的所选字符,其工作方式与上述简单示例类似。
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());
答案 2 :(得分:0)
我认为您需要根据数组的要求从不同的数组中选择字符。这是我的解决方案:
var alphas = "abcdefghjknpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ";
var specials = "!#$%&/()=`";
var numbers = "1234567890";
var requiredSpecials = 1;
var requiredNumbers = 2;
function pickRandom(str, count){
var remaining = str;
var result = "";
while (remaining.length > 0 && count > 0){
// pick random char from remaining
var char = remaining.charAt(Math.floor(Math.random() *remaining.length));
// remove char from remaining. (Just replace with empty string)
remaining = remaining.replace(char, "");
// add char to result
result += char;
// decrement count
count -= 1;
}
return result;
}
function shuffleString(str){
var arr = str.split(''); // Convert to array
arr.sort(function(){ // Sort by random
return 0.5-Math.random()
})
return arr.join(''); // Join back to string
}
function generate(length){
var specialCount = requiredSpecials;
var numberCount = requiredNumbers;
var alphaCount = length - specialCount - numberCount;
var tmp = pickRandom(alphas, alphaCount) + pickRandom(specials, specialCount) + pickRandom(numbers, numberCount);
// Shuffle and return
return shuffleString(tmp);
}
alert(generate(9))
您也可以在jsFiddle
进行游戏