本次將學(xué)習(xí)如何編寫一個(gè)登錄接口小程序。
具體的需求
實(shí)現(xiàn)一個(gè)登錄接口,用戶輸入賬戶密碼即可看到歡迎語句,當(dāng)三次輸入密碼錯(cuò)誤時(shí),則該帳號(hào)被鎖定。
鎖定的意義是,下次使用該賬戶登錄時(shí),將無法成功登錄。
思路
因?yàn)樾枨笥写螖?shù)限制,所以需要有一個(gè)計(jì)數(shù)變量,同時(shí)可能還需要用到while
和if
語句。
需求提到被鎖定的帳號(hào)在程序下一次啟動(dòng)時(shí)仍然記住,眾所周知,python有內(nèi)存回收機(jī)制,程序在結(jié)束之后,所有列表、變量會(huì)從內(nèi)存中抹去,這就需要有一個(gè)文件來存放這些被鎖定的帳號(hào)。
我們需要使用python的open
方法來寫入文件,可以將鎖定帳號(hào)寫入文件,可以命名為blacklist.txt之類的。
blacklist=open("blacklist.txt","w")
此外,需求還需要實(shí)現(xiàn)多用戶的登錄操作,這就需要我們建立一個(gè)用戶密碼的文件,可以命名為admin.txt,每次登錄需要從里面校驗(yàn)用戶名密碼是否正確。
passwd=open("admin.txt","r")
程序邏輯
我們接下來通過流程圖來把整個(gè)過程先梳理一遍:
實(shí)現(xiàn)
因?yàn)樯婕暗接脩裘艽a讀取,用戶名和用戶密碼的一個(gè)對(duì)應(yīng)。
拉入黑名單需要涉及文件寫入的操作,有點(diǎn)復(fù)雜。
可以先用list列表把問題簡(jiǎn)單化。
所以我先用列表代替文件,密碼先只有一個(gè),寫死的。
初步實(shí)現(xiàn)
#owner:houyizhong
#version:demo
admin_name=["houyizhong","test"]
admin_passwd="137010116"
blacklist=["test"]
count = 0
while count < 3:
username=input("Enter your username:")
passwd=input("Enter your password:")
if username not in admin_name:
print("Sorry,your account is not exist!")
continue
elif username in blacklist:
print ("Sorry you are in blacklist!")
exit()
else:
if passwd != admin_passwd:
print("Sorry,enter your password again!")
count += 1
else:
print("Welcome! {0}".format(username))
break
else:
print("Sorry you are in blacklist!")
blacklist.append(username)
exit()
運(yùn)行這段代碼,可以看到:
[root@houyizhong ~]# python login.py
Enter your username:houyizhong
Enter your password:137010116
Welcome! houyizhong
然后開始考慮實(shí)現(xiàn)文件的讀取,寫入操作。
最終實(shí)現(xiàn)代碼:
# -*- coding:utf-8 -*-
#owner:houyizhong
#version1.0
#創(chuàng)建列表
admin_name=[]
admin_passwd=[]
blacklist=[]
#讀取用戶文件
passwd_file=open("admin.txt","r")
admin_list=passwd_file.readlines()
passwd_file.close()
#提取出用戶名,密碼,添加進(jìn)列表
for i in range(len(admin_list)):
admin_parts=admin_list[i]
admin_passwd.append(admin_parts.strip())
admin_part=admin_parts.split(":")
admin_name.append(admin_part[0])
#讀取黑名單文件
blacklist_file=open("blacklist.txt","r")
blacklist_raw=blacklist_file.readlines()
blacklist_file.close()
#提取黑名單用戶名
for i in range(len(blacklist_raw)):
blacklist_value=blacklist_raw[i]
blacklist.append(blacklist_value.strip())
count = 0
while count < 3:
username=input("Enter your username:")
passwd=input("Enter your password:")
if username not in admin_name:
print("Sorry,your account is not exist!")
continue
elif username in blacklist:
print ("Sorry you are in blacklist!")
exit()
else:
if ("{0}:{1}".format(username,passwd)) not in admin_passwd:
print("Sorry,enter your password again!")
count += 1
else:
print("Welcome! {0}".format(username))
break
else:
print("Sorry you are in blacklist!")
blacklist_file=open("blacklist.txt","a")
blacklist_file.write("{0}\n".format(username))
blacklist_file.close()
exit()
改進(jìn)
當(dāng)然這樣還不完美,還有一個(gè)小漏洞,就是這種判斷鎖定的是第三次用戶輸錯(cuò)時(shí)的賬戶,如果有人連續(xù)輸錯(cuò)兩次密碼,再第三次輸入別人的賬戶,故意輸錯(cuò),就會(huì)導(dǎo)致別人的賬戶被鎖定,存在惡意攻擊的漏洞,請(qǐng)看如下演示:
[root@houyizhong pythonprobe]# python login.py
Enter your username:houyizhong
Enter your password:11111
Sorry,enter your password again!
Enter your username:houyizhong
Enter your password:11111
Sorry,enter your password again!
Enter your username:root
Enter your password:1111
Sorry,enter your password again!
Sorry you are in blacklist!
[root@houyizhong pythonprobe]# cat blacklist.txt
root
修正了一下之后,代碼是這樣的,加了一個(gè)while判斷,同時(shí)把輸入密碼的操作放在第二個(gè)循環(huán)里,這樣就避免了惡意鎖定別人的賬戶:
# -*- coding:utf-8 -*-
#owner:houyizhong
#version2.0
#創(chuàng)建列表
admin_name=[]
admin_passwd=[]
blacklist=[]
#讀取用戶文件
passwd_file=open("admin.txt","r")
admin_list=passwd_file.readlines()
passwd_file.close()
#提取出用戶名,密碼,添加進(jìn)列表
for i in range(len(admin_list)):
admin_parts=admin_list[i]
admin_passwd.append(admin_parts.strip())
admin_part=admin_parts.split(":")
admin_name.append(admin_part[0])
#讀取黑名單文件
blacklist_file=open("blacklist.txt","r")
blacklist_raw=blacklist_file.readlines()
blacklist_file.close()
#提取黑名單用戶名
for i in range(len(blacklist_raw)):
blacklist_value=blacklist_raw[i]
blacklist.append(blacklist_value.strip())
count = 0
while count < 3:
username=input("Enter your username:")
if username not in admin_name:
print("Sorry,your account is not exist!")
continue
elif username in blacklist:
print ("Sorry you are in blacklist!")
else:
pass
while count < 3:
passwd=input("Enter your password:")
if ("{0}:{1}".format(username,passwd)) not in admin_passwd:
print("Sorry,enter your password again!")
count += 1
else:
print("Welcome! {0}".format(username))
exit()
else:
print("Sorry you are in blacklist!")
blacklist_file=open("blacklist.txt","a")
blacklist_file.write("{0}\n".format(username))
blacklist_file.close()
exit()
基本部分完成之后,我們?cè)賹?duì)程序優(yōu)化下,目前輸入密碼是明文的,我們可以用getpass模塊來解決這個(gè)問題,優(yōu)化的代碼示例如下:
# -*- coding:utf-8 -*-
#owner:houyizhong
#version2.0
import getpass
#創(chuàng)建列表
admin_name=[]
admin_passwd=[]
blacklist=[]
#讀取用戶文件
passwd_file=open("admin.txt","r")
admin_list=passwd_file.readlines()
passwd_file.close()
#提取出用戶名,密碼,添加進(jìn)列表
for i in range(len(admin_list)):
admin_parts=admin_list[i]
admin_passwd.append(admin_parts.strip())
admin_part=admin_parts.split(":")
admin_name.append(admin_part[0])
#讀取黑名單文件
blacklist_file=open("blacklist.txt","r")
blacklist_raw=blacklist_file.readlines()
blacklist_file.close()
#提取黑名單用戶名
for i in range(len(blacklist_raw)):
blacklist_value=blacklist_raw[i]
blacklist.append(blacklist_value.strip())
count = 0
while count < 3:
username=input("Enter your username:")
if username not in admin_name:
print("Sorry,your account is not exist!")
continue
elif username in blacklist:
print ("Sorry you are in blacklist!")
else:
pass
while count < 3:
passwd=getpass.getpass("Enter your password:")
if ("{0}:{1}".format(username,passwd)) not in admin_passwd:
print("Sorry,enter your password again!")
count += 1
else:
print("Welcome! {0}".format(username))
exit()
else:
print("Sorry you are in blacklist!")
blacklist_file=open("blacklist.txt","a")
blacklist_file.write("{0}\n".format(username))
blacklist_file.close()
exit()
到目前為止,一個(gè)用列表和while
,if
語句判斷的登陸小程序就算完成了。
現(xiàn)在看來用列表來裝這些用戶名密碼什么的還是挺復(fù)雜的,要是用字典就更好了,另外寫入黑名單的操作可以做成def
函數(shù),這樣看起來更清晰,還可以重復(fù)調(diào)用,效率更高。
字典
將源程序中的列表做成字典的形式,用戶名對(duì)應(yīng)密碼,結(jié)構(gòu)更清晰??梢岳米值?dict[username]=passwd
把用戶名的密碼存放,用dict[username]
調(diào)用對(duì)應(yīng)用戶的密碼,同時(shí)加入了一個(gè)old_name
的變量,用來判斷上一次輸入的username
是否和這一次的一樣,不一樣則計(jì)數(shù)變量count
重新開始計(jì)算。
實(shí)現(xiàn)代碼:
#-*- coding:utf-8 -*-
#version3.0
#owner:houyizhong
#create the list and dict
#admin_name=[]
admin_passwd={}
blacklist=[]
#read admin file
admin_file=open("admin.txt","r")
admin_list=admin_file.readlines()
admin_file.close()
#read admin username and password
for i in range(len(admin_list)):
admin_parts=admin_list[i]
admin_raw=admin_parts.strip()
admin_part=admin_raw.split(':')
name=admin_part[0]
passwd=admin_part[1]
admin_passwd[name]=passwd
print(admin_passwd)
#read blacklist file
blacklist_file=open("blacklist.txt","r")
blacklist_raw=blacklist_file.readlines()
blacklist_file.close()
#read blacklist username
for i in range(len(blacklist_raw)):
blacklist_value=blacklist_raw[i]
blacklist.append(blacklist_value.strip())
count = 0
old_name=""
while count < 3:
username=input("username:")
if username != old_name:
count = 0
passwd=input("passwd:")
old_name=username
if username not in admin_passwd:
print ("Sorry ,you account is not exist!")
continue
elif username in blacklist:
print ("Sorry ,you are in the blacklist!")
exit()
else:
if passwd != admin_passwd[username]:
count += 1
print("Sorry,you password is wrong.")
else:
print ("Welcome!{0}".format(username))
break
else:
print ("You are in blacklist now!")
blacklist_file=open("blacklist.txt","a")
blacklist_file.write("{0}\n".format(username))
blacklist_file.close()
exit()
實(shí)現(xiàn)效果:
[houyizhong@localhost py]$ python login.py
username:test
passwd:
Sorry,you password is wrong.
username:test
passwd:
Sorry,you password is wrong.
username:root
passwd:
Sorry,you password is wrong.
username:root
passwd:
Welcome!root
好了,大功告成了,這一階段的學(xué)習(xí)就到這里啦~