我有以下方法来生成随机密码:
char_set = {
'small': 'abcdefghijklmnopqrstuvwxyz',
'nums': '0123456789',
'big': 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
'special': '^!\$%&/()=?{[]}+~#-_.:,;<>|\\'
}
def gen_password(length=21):
'''
Generate a random password containing upper and lower case letters,
numbers and special characters.
Arguments:
----------
The default length is 21 chars, however the minimum is 8 chars.
Returns:
--------
str: The random password
'''
assert length >= 8
password = []
while len(password) < length:
key = random.choice(char_set.keys())
a_char = os.urandom(1)
if a_char in char_set[key]:
if check_prev_char(password, char_set[key]):
continue
else:
password.append(a_char)
return ''.join(password)
def check_prev_char(password, current_char_set):
'''
Ensure that there are not consecutive Uppercase / Lowecase / Number / special
characters in the password.
Arguments:
----------
password: (str)
The candidate password
current_char_set: (char)
The current character to be compared.
Returns:
--------
Bool: if the candidate password is good so far.
'''
index = len(password)
if index == 0:
return False
else:
prev_char = password[index - 1]
if prev_char in current_char_set:
return True
else:
return False
虽然它在大多数情况下都有效,但有一些情况会失败,例如,当密码有\
或没有号码时。
如何确保我生成的所有密码都不包含\
,并且始终至少包含一个数字?
答案 0 :(得分:2)
如果您不想在密码中使用\
,请将其从特殊字符集中删除(这是否有原因?):
'special': '^!\$%&/()=?{[]}+~#-_.:,;<>|'
要确保它始终有一个数字,请生成一个包含n-1
个字符的密码,然后在随机位置添加一个数字:
def gen_final_password(length=21):
password = gen_password(length - 1)
index = random.randint(0, length)
number = random.choice(char_set['nums'])
return password[:index] + number + password[index:]
但请注意,这可能无法生成具有完整预期熵的加密随机密码。为此,您需要始终使用加密随机源并使用具有相同可能性的所有字符。现在,算法更喜欢小字符集中的字符(例如,它更可能包含0
而不是a
)。此外,避免相同字符集的连续字符对熵具有未知,不良影响。
最后,check_prev_char
可以简化为表达式:
len(password) and password[-1] in char_set[key]
答案 1 :(得分:0)
^(?!.*\\)(?=.*\d).*$
您可以在结尾处re.match
确保password
没有/
并且至少有一个\d
。
答案 2 :(得分:0)
如果您不希望生成的密码包含&#39; \&#39;,为什么不从定义的char_set中删除该字符,从中获取密码的字符?
至于生成始终至少有一个数字的密码,您可以在返回之前检查生成的密码,然后在返回密码之前用随机数覆盖随机字符(如果需要数字)。