1、參考模型,此作業我參考了linux的登入認證流程以及結合網路銀行支付寶等鎖定規則;
# 1)認證流程參考的是Linux的登入:當你輸入完使用者名稱密碼後再驗證使用者名稱是否有使用者是否被鎖定,然後在驗證密碼是否正確,如果驗證不過去只會告訴你驗證失敗,而不告訴你到底是使用者名稱錯誤還是密碼錯誤,增加了暴力破解的難度;
2)關於輸入錯誤次數的計數和鎖定,我參考的是銀行和支付寶的做法,也就是只關心你輸錯了多少次,不關心輸對了多少次,也就是說輸錯了兩次,第三次輸了,前面的數不清零,也就是你今天輸入了1000次輸對了997次,只輸錯了3次,那對不起,依然要鎖定。而且輸入錯誤的3次不一定要連續。只要三次輸入錯誤三次就鎖定。
2、關於計數和狀態的保存我考慮還是透過檔案來持久化保存,每次輸入錯誤次數的累加和鎖定都保存到文件中,這樣雖然增加了文件的操作,但是保證了程序的可靠性,這樣程序退出,計數仍然有效。文件類型如下:
alex sb lock 3
tom 666 unlock 0
geng 888 unlock 2
是用戶名,第二列是密碼,第三列是使用者狀態(lock代表鎖定,unlock代表沒有鎖定),第四列是登入次數(其實,登入次數只要錯誤的時候登入次數加一即可,沒有錯誤的時候不用管它)。
程式碼如下:
with open(filename,) key,values lines = print( f.write( .join(lines) + values.insert( f.write( .join(values) + # messages = {:[,,],:[,,],:[,, # write_file(messages, __name__ == active = username = input( users_dict = {} #用户字典,用于存放用户的信息,键-用户名,值- with open(,) lines = line user_list = users_dict[user_list[]] = user_list[ username users_dict[username][] == print( (users_dict[username][]) < user_pwd = input( users_dict[username][] == print( (users_dict[username][]) != print( % ( - (users_dict[username][ users_dict[username][] = (users_dict[username][]) + print( users_dict[username][] = users_dict[username][] = write_file(users_dict, elif username == print() 运行结果如下: 请输入你的用户名(输入quit退出):tom 请输入密码:22 还有2次机会,用户将被锁定! 请输入密码:22 还有1次机会,用户将被锁定! 请输入密码:22 对不起,您输入的次数过多,你的用户名已经被锁定,请联系管理员! 请输入你的用户名(输入quit退出):alex 您输入的用户名已经锁定,请联系管理员!
其實對文件的操作,其本質上還是對字串列表,字典的操作,文件的操作,讀取文件的方法,readlines()按行讀取存放到一個列表中,使用dict(字典)記錄用戶資訊。字串的拼接(join)方法,(" ".join(list)),字串與列表進行拼接,形成一個新的字串,其實字串的本質上在python中儲存的形式就是以列表的形式存儲,列表之間的拼接,list.extend(list),列表之間的拼接。
程式碼說明:
# 1、這裡用了兩個今天課程沒講的內容:字典和函數,使用者資訊以字典的方式保存是出於判斷用戶名是否存在的考慮,讀文件的時候直接將用戶名作為字典的一個key,其他的信息作為字典的value與key一一對應,這樣在判斷用戶名是否存在只需要透過in這個成員運算子來判斷就可以了;
2、程式碼的第61、62兩行程式碼完成的就是將檔案變成字典的過程。
原創張曉宇程式碼實例:
#!/usr/bin/env python3 # coding:utf-8'''Created on: 2015年12月29日 @author: 张晓宇 Email: 61411916@qq.com Version: 1.0Description: 输入用户名密码,认证成功显示欢迎信息,认证失败,输错三次后锁定 Help:'''import os # 定义用户信息写入函数,用于把用户信息写回文件 def write_to_account_file(accounts,account_file_path):"""accounts是一个用户信息字典,目的是把变更过的信息写入文件中"""account_file = open(account_file_path,"w")for key,val in accounts.items(): line = [] line.append(key) line.extend(val) print(" ".join(line)) #字符串与列表拼接,目的是实现列表中每个元素加空格生成一个字符串如a b c d格式 account_file.write(" ".join(line) + "\n") #往文件中添加信息 account_file.close() #直接打开文件的时候一定要记得关闭文件,以免文件休息丢失if __name__ == '__main__':''' @parameters: account_file_path:账户文件 password_col_num:账户文件中密码所在的列(从0开始) status_col_num:账户文件中账户状态所在的列(从0开始) error_count_num:账户文件中输入错误次数所在的列(从0开始) app_info:系统信息,用户启动应用后的输出 welcome_msg:用户成功登录后的信息''' account_file_path = 'account.db'password_col_num = 1status_col_num = 2error_count_num = 3app_info = ''' +---------------------------------+ | Welcome to gcx system | | Version:2.0 | | Author:zhuzhu | +---------------------------------+''' welcome_msg = "Welcome %s,authentication is successful!"if os.path.exists(account_file_path): #os.path.exists()判断文件是否存在,返回布尔值 # 判断账户文件是否存在 account_file = open(account_file_path,"r")else: #文件不存在,看系统是否有误 print("Error:Account file 'account.db' is not exit,please check!") exit(1) #读账户文件 accounts = {}for line in account_file.readlines(): #按行读取文件 account = line.strip().split() #清楚空格后进行分列,生成一个列表 accounts[account[0]] = account[1:]"""把列表中的第一个元素(用户名)当做键,用户的其他信息当做值,组成键值对存放在字典中""""""account[0]键,account[1:]是值"""account_file.close() #关闭文件 flag = Truewhile flag: print(app_info) #输入用户名 username = input("Username(Enter quit to exit): ").strip() #判断用户是否输入的为quitif username == "quit": #是则退出循环,程序结束breakpassword = input("Password: ").strip() #判断用户名是否存在if username not in accounts.keys(): #不存在提示错误信息并退出当前循环让用户重新输入 print("Error:Username or Password it is error!")continue #结束本次循环,让用户再次输入用户名和密码,继续执行下一次循环if accounts[username][status_col_num - 1] == "lock": #如果被锁定退出当前循环让用户重新输入 print("Error:Account is locked.Please contact the administrator!")continue #跳过本次循环,让用户重新输入进行验证,这个可以避免很多缩进,能够继续执行下一次 #判断用户密码是否正确if password == accounts[username][password_col_num - 1]: #正确显示欢迎信息 print(welcome_msg %username)breakelse: #用户密码不正确的情况 #提示用户名或密码错误 print("Error:Username or Password it is error!") #输入错误次数加1 accounts[username][error_count_num - 1] = str(int(accounts[username][error_count_num - 1]) + 1) #判断是否已经达3次if int(accounts[username][error_count_num - 1 ]) == 3: #如果输入错误达到3次 #提示账户将被锁定 print("Error: This account will be locked,Please contact the administrator!System will be exit!") #将用户状态改为lock并写入文件 accounts[username][status_col_num - 1] == "lock"write_to_account_file(accounts,account_file_path)breakwrite_to_account_file(accounts,account_file_path)
上述程式碼中亮點:
(1)continue:結束這次循環,continue後面的程式碼都不執行,達到重新讓使用者輸入的目的,很多網頁都是讓使用者一直輸入,知道使用者要麼選擇註冊,要麼關掉網頁;
(2)文件的規範性較好,並有解釋;
# (3)文件就是一行一行讀,然後一行一行寫入文件,修改的過程中要用到列表和字典的知識;
(4) " ".join(list)字串與列表的拼接,產生新的字串;
(5)split()字串的分割;extend()列表之間的拼接。
以上是撰寫登入視窗的具體步驟詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!