2015-11-18 40 views
1

我試圖爲具有以下密碼要求的Active Directory生成隨機密碼:至少8個字符,至少一個特殊字符,至少一個數字,至少一個小寫和至少一個大寫字母。在Python 3中生成需求隨機字符串

通過以下代碼,我可以生成一個隨機密碼並檢查它是否包含特殊字符。生成新密碼直到找到特殊字符。

special_char = "[email protected]%/()=?+.-" 

password_string = "".join([random.choice(string.ascii_lowercase + string.ascii_digits + string.ascii_uppercase + special_char) for n in range(8)]) 

while any(c in password_string for c in special_char) is not True: 
    password_string = "".join([random.choice(string.ascii_lowercase + string.ascii_digits + string.ascii_uppercase + special_char) for n in range(8)]) 

的問題,以下是它的唯一檢查的特殊字符,並生成一個新的密碼可能擺脫對方要求假設他們的存在。我怎樣纔能有效地執行AD密碼要求?謝謝你的幫助。

+1

另一種說法:不要使用'(boolean expr)不是真的';使用'not(boolean expr)'。 –

回答

5

您可以生成一個匹配的密碼,首先,先採摘特殊字符和一個數字(和一個較低並以同樣的方式一個大寫字母),填補了任何事情,並最終洗牌的順序:

pwlist = ([random.choice(special_char), 
      random.choice(string.ascii_digits), 
      random.choice(string.ascii_lowercase), 
      random.choice(string.ascii_uppercase), 
      ] 
     + [random.choice(string.ascii_lowercase 
          + string.ascii_uppercase 
          + special_char 
          + string.ascii_digits) for i in range(4)]) 
random.shuffle(pwlist) 
pw = ''.join(pwlist) 
+0

好的解決方案....我喜歡它。最終密碼中每個字符類的預期字符數可能與OP算法不同......但我不認爲這是一個約束。 – Jug

+0

@Jug:是的,「感覺真」,這應該具有隨機性的相同性質的「始亂終棄,直到你得到它的權利」,但它不會立即明顯。 –

+0

這是輝煌的,謝謝! – strongbad

2

測試while測試中的所有條件。這是比較容易委派有效密碼測試功能:

special_char = "[email protected]%/()=?+.-" 
password_characters = string.ascii_letters + string.ascii_digits + special_char 

def is_valid(password): 
    if len(password) < 8: 
     return False 
    if not any(c in password for c in special_char): 
     return False 
    if not any(c.isdigit() for c in password): 
     return False 
    if not any(c.islower() for c in password): 
     return False 
    if not any(c.isupper() for c in password): 
     return False 
    return True 

password_string = '' 
while not is_valid(password_string): 
    password_string = "".join([random.choice(password_characters) 
           for n in range(8)]) 
+0

該解決方案具有不幸的可能性,即浪費時間無效,直到滿足所有要求。 – DevPlayer

+0

@DevPlayer:理論上,循環可以永久運行。在實踐中,你永遠不會注意到。但是,是的,選擇一個隨機數字,隨機特殊字符,隨機小寫和隨機大寫字母,填充了這一點,所有有效的字符和洗牌的結果是要避免的理論永遠的循環。 –

+0

感謝您的建議! – strongbad

2

使用集和交集強制約束...

import string 
import random 

special_char = "[email protected]%/()=?+.-" 
set_lower = set(string.ascii_lowercase) 
set_upper = set(string.ascii_uppercase) 
set_digits = set(string.digits) 
set_sp = set(special_char) 

all_chars = string.ascii_lowercase + \ 
    string.digits + \ 
    string.ascii_uppercase + \ 
    special_char 

password_string = "".join([random.choice(all_chars) for n in range(8)]) 

def isOK(pw): 
    pw = set(pw) 
    for x in (set_lower, set_upper, set_digits, set_sp): 
     if len(pw.intersection(x)) == 0: 
      return False 
    return True 

while not isOK(password_string): 
    password_string = "".join([random.choice(all_chars) for n in range(8)]) 

print password_string 
+1

'string.lowercase'和'string.uppercase'因語言環境而異。我會堅持'string.ascii_letters'(同時包含'string.ascii_lowercase'和'string.ascii_uppercase')。 –

+0

@MartijnPieters謝謝......更新。 – Jug

+0

對於while循環的每次迭代,此解決方案都有一個不幸的問題。 – DevPlayer

0

你可以小鬼字元素由一個要求之一..

  • 至少8個字符
  • 至少一個特殊字符
  • 至少一個數位
  • 至少一個小寫和
  • 至少一個大寫。

所以你做任何事情之前 創建一個由 1隨機選擇的特殊字符的字符串。 隨機選擇1位數字。 隨機選擇1個小寫字符。 和1個大寫字符隨機選擇。在總 這就是4個字符,剩餘的字符可以被隨機選擇的,長度必須大於8.

所有生成的密碼就不會是有效的,所以沒有必要檢查該..

現在你可以抱怨的密碼都將具有相同的可預測的模式: 特殊,數字,小寫字母,大寫的,隨機的東西..

,所以我們將它洗..

import string 
SpecialChars = "[email protected]%/()=?+.-" 

password = "" 

import random 
password += random.choice(string.ascii_uppercase) 
password += random.choice(string.ascii_lowercase) 
password += random.choice(string.digits) 
password += random.choice(SpecialChars) 

i = random.randint(4, 8) 

for i in range(0,i): 
    password += random.choice(string.ascii_uppercase + string.ascii_lowercase + string.digits+ SpecialChars) 

password = ''.join(random.sample(password,len(password))) 

print password 
+0

在這裏使用'string.ascii_digits'有什麼問題?對於一個範圍內的隨機整數,只需使用'random.randint(4,8)'。 –

+0

不錯的優化點。 – Henrik

1

我喜歡ULR ich的答案更好。他打敗了我。

import string 
import random 
string_specials = '[email protected]%/()=?+.-' 
string_pool = string_specials + string.ascii_letters + string.digits 
pre_password = [ 
    random.choice(string_specials), 
    random.choice(string.ascii_uppercase), 
    random.choice(string.ascii_lowercase), 
    random.choice(string.digits), 
    random.choice(string_pool), 
    random.choice(string_pool), 
    random.choice(string_pool), 
    random.choice(string_pool)] 
scrambled = [] 
while pre_password: 
    scrambled.append(pre_password.pop(random.randint(0, len(pre_password)-1))) 
password = ''.join(scrambled)