目录
前言
打基础,学Web安全还是得先落实到开发学习上。
接下来将以简单小项目为单位锻炼自己的实操能力,计划寒假前完成python的部分,寒假专注java部分。这期间的博客主要记录开发学习内容,磨刀不误砍柴工。
项目说明
通常情况下,如果利用文本文件来保存数据,有三种数据可供使用:
1.CSV文件
2.XML文件
3.JSON文件(频率最高)
这里我们选用第一种CSV文件
简单说明功能的实现:
要求一
1.用户注册时必须要输入用户名、密码、手机号码,针对用户的输入必须验证。
2.用户名的规则:只能是大小写字母或数字,且不能以数字开头,长度为5~12位。
3.密码的规则:密码必须且只能由大小写字母和数字组成,长度为6~15位。
4.手机号码的规则:按照标准的中国手机号码规则进行校验。
5.如果校验成功,则允许用户注册,注册信息保存于列表或字典中,否则要求用户继续输入。
要求二
1.基于命令行给用户设定一个菜单,让用户可以决定下一步干什么。
2.支持多用户注册,注册时,如果已经存在的用户名不能注册。
3.将注册的用户名密码电话等信息,保存在文本文件中(CSV文件)。
4.实现用户的登录功能,用于登录验证。
5.在使用CSV保存用户数据的情况下,让用户可以修改密码(输入用户名、旧密码、新密码)
代码实现
先创建一个exercise包,自动生成__init__.py,包里放app.py(主程序),common.py(通用函数模块),userpass.csv(用于储存读写数据的CSV文件)
app.py
from exercise.common import *
def input_username():
# global username
username=input("请输入用户名: ")
if check_username(username):
if check_user_exists(username):
print("用户名已存在.")
return input_username()
else:
print("用户名正确.")
return username
else:
print("用户名错误.")
return input_username()
def input_password():
# global password
password=input("请输入密码: ")
if check_password(password):
print("密码正确.")
return password
else:
print("密码错误.")
return input_password()
def input_phone():
# global phone
phone=input("请输入手机号: ")
if check_phone(phone):
print("手机号正确.")
return phone
else:
print("手机号错误.")
return input_phone()
def do_reg():
username=input_username()
password=input_password()
phone=input_phone()
with open('./userpass.csv',mode='a') as f:
f.write(f"\n{username},{password},{phone}")
print("恭喜你,注册成功.")
draw_menu()
def do_login():
username=input("请输入用户名:")
password=input("请输入密码:")
user=check_get_user(username)
if user is None:
print("用户名不存在.")
exit(0)
elif user['password']==password:
print("用户名密码正确,登录成功.")
else:
print("登录失败.")
draw_menu()
def do_change():
username = input("请输入用户名:")
password = input("请输入密码:")
user = check_get_user(username)
if user is None:
print("用户名不存在.")
draw_menu()
elif user['password']==password:
newpass=input("请输入新密码:")
change_password(username,newpass)
else:
print("旧密码验证不通过.")
def draw_menu():
print("======== 请选择菜单项 ========")
print("1、注册 2、登录 3、修改密码 4、退出")
option=input("请选择菜单项:[1,2,3,4]:")
if option=='1':
do_reg()
elif option=='2':
do_login()
elif option=='3':
do_change()
elif option=='4':
exit(0)
else:
print("请输入正确的菜单编号.")
draw_menu()
if __name__ == '__main__':
draw_menu()
common.py
import re
'''
长度的判断5-12位,使用len函数进行判断
不能以数字开头:username[0]不能是0-9的范围
判断只能是大小写或数字:
返回值:True:用户名正确,False:用户名错误
'''
def check_username(username):
if len(username) < 5 or len(username) > 12:
return False
if username[0] >= '0' and username[0] <= '9':
return False
for char in username:
if not (ord(char) in range(65,91) or ord(char) in range(97,123) or ord(char) in range(48,58)):
return False
return True
'''
检查密码:由大写、小写和数字构成,且必须是6-15位
只要确保密码中至少有1位是大写,至少有1位是小写,至少有1位是数字
'''
def check_password(password):
if len(password)<6 or len(password)>15:
return False
lower,upper,digit,other=0,0,0,0
for char in password:
if char>='A' and char<='Z':
upper+=1
elif char>='0' and char<='9':
digit+=1
elif char>='a' and char<='z':
lower+=1
else:
other+=1
if upper<1 or lower<1 or digit<1 or other>0:
return False
return True
def check_phone(phone):
pattern = "^1[3-9]\d{9}$"
if re.match(pattern,phone):
return True
else:
return False
#读取CSV,并动态将第一行作为字典的key,返回[{},{}]的格式
def read_csv(csvfile,has_column=True):
with open(csvfile) as f:
line_list=f.readlines()
if not has_column:
raise Exception("CSV文件必须要使用第一行作为列名")
key_list=line_list[0].strip().split(',')
list=[]
for i in range(1,len(line_list)):
temp_list=line_list[i].strip().split(',')
dict={}
for j in range(len(key_list)):
dict[key_list[j]]=temp_list[j]
list.append(dict)
return list
#读取CSV文件,并检查用户名是否存在
def check_user_exists(username):
user_list=read_csv('./userpass.csv')
for user in user_list:
if user['username']==username:
return True
return False
#根据用户名取得CSV文件中对应的一行用户数据,以字典的形式返回
def check_get_user(username):
user_list=read_csv('./userpass.csv')
for user in user_list:
if user['username']==username:
return user
return None
#修改用户的密码,修改一个CSV文件中的某一行中的某一列,不能直接修改(Python中不存在文件内容部分修改的操作)
#将CSV整体读入到内存中,形成列表+字典,然后修改字典的某一项,再整体覆盖写入到CSV
def change_password(username,newpass):
csv_list=read_csv('./userpass.csv')
for user in csv_list:
if user['username']==username:
index=csv_list.index(user)
break
csv_list[index]['password']=newpass
#将列表+字典还原成行+逗号分割数据
with open('./userpass.csv',mode='w') as f:
f.write("username,password,phone\n")
for user in csv_list:
line=f"{user['username']},{user['password']},{user['phone']}\n"
f.write(line)
#全自动的单元测试代码,编写一个测试驱动程序
def test_driver(func,expect,*args):
actual=func(*args)
if actual==expect:
print("测试 %s:成功" %func.__name__)
else:
print("测试 %s: 失败" %func.__name__)
if __name__=='__main__':
pass
# test_driver(check_password,True,'123456789')
userpass.csv
username,password,phone
czr,czr123,13112345678
admin,admin123,13212345678
root,root123,13312345678
hack,hack123,13412345678
Z3r4y,Z3r4y123,13123456789
CubicU,CubicU123,13123456789
suibian,Asuibian123,13123456789