实现用户注册与校验
common—源码
"""
一、基础功能需求1. 综合使用当前所学知识,如列表、字典、字符串、函数等,实现一个基于命令行的用户注册功能。
2. 用户注册时必须要输入用户名、密码、手机号码,用针对用户的输入必须进行验证。
3. 用户名的规则:只能是大小写字母或数字,且不能以数字开头,长度为5~12位。
4. 密码的规则:密码必须且只能由大小写和数字组成,长度为6~15位。
5. 手机号码的规则:按照标准的中国手机号码规则进行校验。
6. 如果校验成功,则允许用户注册,注册信息保存于列表或字典中,否则要求用户继续输入。需求2.0(1) 基于命令行给用户设定一个菜单,让用户可以决定下一步干什么。
(2) 支持多用户注册,注册时,如果已经存在的用户名不能注册。
(3) 将注册的用户名密码电话等信息,保存在文件文件中(CSV文件)。
(4) 实现用户的登录功能,用于登录校验。
(5) 在使用CSV保存用户数据的情况下,让用户可以修改密码(输入用户名、旧密码和新密码)。
(6) 用户在输入用户名、密码或电话时,如果输超过三次,则结束运行。二、功能代码实现1. 结构设计
(1)以什么结构来保存用户信息?[]列表不方便管理,{}字典效果好点。
如果针对多个用户呢?使用标准的[{},{},{}]列表嵌入字典的方式。
(2)有很多的校验,是否可以用函数进行管理?check_username(),check_password(),check_phone(),input_user(),input_password(),input_phone(),do_reg()
(3)有明确的提示信息,有明确的错误信息,代码的运行过程,如何提升用户体验。
2. 代码实现
"""
import re
import pymysql
from pymysql.cursors import DictCursor"""
用户名检查
长度的判断5~12位,使用len函数进行判断。
不能以数字开头,username[0]不能是0~9的范围。
如何判断只能是大小写或数字
返回值True:用户名正确,False:用户名错误
"""def check_username(username):if len(username) < 5 or len(username) > 12:# return函数用于函数中return Falseif '0' <= username[0] <= '9':return Falsefor 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 Falsereturn True"""
检查密码:由大小写和数字构成,长度6~15位。
只要确保密码中至少有1位是大写,至少有一位是小写,至少有一位是数字。
"""def check_password(password):if len(password) < 6 or len(password) > 15:return Falselower = 0upper = 0digit = 0other = 0for char in password:if 'A' <= char <= 'Z':upper += 1elif 'a' <= char <= 'z':lower += 1elif '0' <= char <= '9':digit += 1else:other += 1if upper < 1 or lower < 1 or digit < 1 or other > 0:return Falsereturn True# 检查电话号码
def check_phone(phone):pattern = "^1[3-9]\d{9}$"if re.match(pattern, phone):return Trueelse:return Falsedef read_csv(csvfile, has_column=True):with open('users.csv') as f:line_list = f.readlines()if not has_column:raise Exception('csv文件必须要使用第一行作为列名')# return Nonekey_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(temp_list)):dict[key_list[j]] = temp_list[j]list.append(dict)return list# 读取csv文件,并检查用户名是否存在
def check_user_exists(username):user_list = read_csv('users.csv')for user in user_list:if user['username'] == username:return Truereturn False# 根据用户名取的csv文件中对应的一行用户数据
def check_get_user(username):user_list = read_csv('users.csv')for user in user_list:if user['username'] == username:return userreturn None# 修改用户密码,修改一个csv文件中的某一列,不能直接修改(python中不存在文件内容修改一说)
# 将csv整体读入内存中,进行修改,形成列表加字典,再覆盖写入
def change_password(username, newpass):csv_list = read_csv('users.csv')for user in csv_list:if user['username'] == username:index = csv_list.index(user)breakcsv_list[index]['password'] = newpass# 将列表加字典还原成行+逗号with open('users.csv', 'w') as f:f.write("username,password,phone\n")for user in csv_list:line = f"{user['username']}, {user['password']}, {user['phone']}\n"line = line.replace("'", "")f.write(line)# 针对数据库进行封装操作
def query_mysql(sql):conn = pymysql.connect(host='localhost', user='root', password='root', database='semcms', charset='utf8',autocommit=True)cursor = conn.cursor(DictCursor)cursor.execute(sql)result = cursor.fetchall()conn.close()return result# 封装update
def update_mysql(sql):conn = pymysql.connect(host='localhost', user='root', password='root', database='semcms', charset='utf8',autocommit=True)cursor = conn.cursor(DictCursor)cursor.execute(sql)conn.close()def query_mysql_2(sql):try:conn = pymysql.connect(host='localhost', user='root', password='root', database='semcms',charset='utf8', autocommit=True)cursor = conn.cursor(DictCursor)cursor.execute(sql)result = cursor.fetchall()return resultexcept:raise Exception("数据库处理出错")finally:conn.close()# 全自动单元测试代码
def test_driver(func, expect, *args):actual = func(*args)if actual == expect:print("测试 %s: 成功" % func.__name__)else:print("测试 %s: 失败" % func.__name__)if __name__ == '__main__':"""
测试用户名的规则 TDD
test_driver(check_username, True, 'dad%ad') # 失败
测试密码的规则
test_driver(check_password, True, 'Afd1sa121') # 成功
测试电话号码规则
test_driver(check_phone,True,'13345678910') # 成功
通常情况下,利用文本文件来保存数据,有三种数据格式可供使用
1、csv文件
2、xml文件
3、json文件"""
common—源码分析
这段代码实现了一个基于命令行的用户注册系统,包含了用户注册、登录、修改密码等功能,并且将用户信息保存在CSV文件中。以下是对代码的详细分析:
一、基础功能需求
-
用户注册功能:
-
用户需要输入用户名、密码、手机号码。
-
对用户输入进行验证,确保符合规则。
-
-
用户名规则:
-
长度为5~12位。
-
只能包含大小写字母或数字。
-
不能以数字开头。
-
-
密码规则:
-
长度为6~15位。
-
必须包含至少一个大写字母、一个小写字母和一个数字。
-
-
手机号码规则:
-
符合中国手机号码标准(11位,以1开头,第二位为3-9)。
-
-
注册信息保存:
-
注册成功后,信息保存在CSV文件中。
-
二、功能代码实现
-
结构设计:
-
使用列表嵌套字典的方式保存多个用户信息。
-
使用函数进行输入验证和注册操作。
-
-
代码实现:
用户名检查
def check_username(username):if len(username) < 5 or len(username) > 12:return Falseif '0' <= username[0] <= '9':return Falsefor 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 Falsereturn True
密码检查
def check_password(password):if len(password) < 6 or len(password) > 15:return Falselower = 0upper = 0digit = 0other = 0for char in password:if 'A' <= char <= 'Z':upper += 1elif 'a' <= char <= 'z':lower += 1elif '0' <= char <= '9':digit += 1else:other += 1if upper < 1 or lower < 1 or digit < 1 or other > 0:return Falsereturn True
手机号码检查
def check_phone(phone):pattern = "^1[3-9]\d{9}$"if re.match(pattern, phone):return Trueelse:return False
读取CSV文件
def read_csv(csvfile, has_column=True):with open('users.csv') 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(temp_list)):dict[key_list[j]] = temp_list[j]list.append(dict)return list
检查用户名是否存在
def check_user_exists(username):user_list = read_csv('users.csv')for user in user_list:if user['username'] == username:return Truereturn False
修改密码
def change_password(username, newpass):csv_list = read_csv('users.csv')for user in csv_list:if user['username'] == username:index = csv_list.index(user)breakcsv_list[index]['password'] = newpasswith open('users.csv', 'w') as f:f.write("username,password,phone\n")for user in csv_list:line = f"{user['username']}, {user['password']}, {user['phone']}\n"line = line.replace("'", "")f.write(line)
数据库操作
def query_mysql(sql):conn = pymysql.connect(host='localhost', user='root', password='root', database='semcms', charset='utf8', autocommit=True)cursor = conn.cursor(DictCursor)cursor.execute(sql)result = cursor.fetchall()conn.close()return result
三、测试代码
def test_driver(func, expect, *args):actual = func(*args)if actual == expect:print("测试 %s: 成功" % func.__name__)else:print("测试 %s: 失败" % func.__name__)
四、改进建议
-
用户体验:
-
在用户输入错误时,提供明确的错误信息。
-
限制用户输入错误次数,超过三次则结束程序。
-
-
代码优化:
-
使用
csv
模块来读写CSV文件,避免手动处理字符串。 -
数据库操作可以进一步封装,增加异常处理。
-
-
安全性:
-
密码应加密存储,避免明文保存。
-
数据库连接信息应从配置文件读取,避免硬编码。
-
通过以上分析,可以看出这段代码实现了基本的功能需求,但在用户体验、代码优化和安全性方面还有改进空间。
input—源码
from 基于网安的学习.python源.实现用户注册与校验.common import check_username, check_password, check_phone, \check_user_exists, check_get_user, change_password, query_mysql, update_mysql"""
username = ''
password = ''
phone = ''
"""def input_username():# global usernameusername = input("请输入用户名:")if check_username(username):if check_user_exists(username):print("用户名已存在")return input_username()else:print("用户名正确")return usernameelse:print("用户名错误")return input_username() # 循环调用函数自身,完成循环的功能def input_password():# global passwordpassword = input("请输入密码:")if check_password(password):print("密码正确")return passwordelse:print("密码错误")return input_password()def input_phone():# global phonephone = input("请输入电话号:")if check_phone(phone):print("电话正确")return phoneelse:print("电话错误")return input_phone()def do_reg():username = input_username()password = input_password()phone = input_phone()if check_user_exists(username):print("您的用户名已经被注册:")else:with open('users.csv', 'a') as f:f.write(f"{username},{password},{phone}\n")print("恭喜你,注册成功!")draw_nemu()"""
def do_reg1():username = input("请输入用户名:")password = input("请输入密码:")phone = input("请输入电话号码:")result = query_mysql("select user_name from sc_user where user_name='{username}'")if len(result) == 0:update_mysql("insert into sc_user(user_name,user_admin,user_ps,user_time) values('{user_name}','{user_admin}',""'{user_ps}',now())")else:print("用户名已存在,不允许注册")
"""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_nemu()def do_change():username = input("请输入用户名:")password = input("请输入旧密码:")user = check_get_user(username)if user is None:print("用户名不存在")draw_nemu()elif user['password'] == password:newpass = input("请输入新密码")change_password(username, newpass)def draw_nemu():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()else:print("请输入正确的菜单编号")"""user_list = []users = {'username': username, 'password': password, 'phone': phone}user_list.append(users)print(user_list)
"""if __name__ == '__main__':draw_nemu()
input—源码分析
这段代码实现了一个基于命令行的用户注册、登录和修改密码系统。以下是对代码的详细分析:
一、功能概述
-
用户注册:
-
用户输入用户名、密码和电话号码。
-
对输入进行验证,确保符合规则。
-
如果用户名已存在,则提示用户重新输入。
-
注册成功后,将用户信息保存到CSV文件中。
-
-
用户登录:
-
用户输入用户名和密码。
-
验证用户名和密码是否匹配。
-
如果匹配成功,则登录成功;否则,提示登录失败。
-
-
修改密码:
-
用户输入用户名和旧密码。
-
验证用户名和旧密码是否匹配。
-
如果匹配成功,则允许用户输入新密码并更新。
-
-
菜单系统:
-
提供一个简单的菜单系统,让用户选择注册、登录、修改密码或退出。
-
二、代码分析
输入函数
-
输入用户名:
def input_username():username = input("请输入用户名:")if check_username(username):if check_user_exists(username):print("用户名已存在")return input_username()else:print("用户名正确")return usernameelse:print("用户名错误")return input_username()
-
输入密码:
def input_password():password = input("请输入密码:")if check_password(password):print("密码正确")return passwordelse:print("密码错误")return input_password()
-
输入电话号码:
def input_phone():phone = input("请输入电话号:")if check_phone(phone):print("电话正确")return phoneelse:print("电话错误")return input_phone()
注册函数
def do_reg():username = input_username()password = input_password()phone = input_phone()if check_user_exists(username):print("您的用户名已经被注册:")else:with open('users.csv', 'a') as f:f.write(f"{username},{password},{phone}
")print("恭喜你,注册成功!")draw_nemu()
登录函数
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_nemu()
修改密码函数
def do_change():username = input("请输入用户名:")password = input("请输入旧密码:")user = check_get_user(username)if user is None:print("用户名不存在")draw_nemu()elif user['password'] == password:newpass = input("请输入新密码")change_password(username, newpass)
菜单系统
def draw_nemu():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()else:print("请输入正确的菜单编号")
三、改进建议
-
安全性:
-
密码应加密存储,避免明文保存。
-
数据库连接信息应从配置文件读取,避免硬编码。
-
-
用户体验:
-
在用户输入错误时,提供明确的错误信息。
-
限制用户输入错误次数,超过三次则结束程序。
-
-
代码优化:
-
使用
csv
模块来读写CSV文件,避免手动处理字符串。 -
数据库操作可以进一步封装,增加异常处理。
-
-
功能扩展:
-
可以增加用户注销功能。
-
可以增加用户信息查看功能。
-
通过以上分析,可以看出这段代码实现了基本的功能需求,但在用户体验、代码优化和安全性方面还有改进空间。