我的Python成长之路---第一天---Python基础(作业1:登录验证)---2015年12月26日(雾霾)
作业一:编写登录接口
- 输入用户名密码
- 认证成功系那是欢迎信息
- 输错三次后锁定
思路:
1、参考模型,这个作业我参考了linux的登录认证流程以及结合网上银行支付宝等锁定规则
1)认证流程参考的是Linux的登录:当你输入完用户名密码后再验证用户名是否存在用户是否被锁定,然后在验证密码是否正确,如果验证不过去只会告诉你验证失败,而不告诉你到底是用户名错误还是密码错误,增加了暴力破解的难度。如下图所示

2)关于输入错误次数的计数和锁定,我参考的是银行和支付宝的做法,也就是只关心你输错了多少次,不关心输对了多少次,也就是说输错了两次,第三次输对了,前面的计数不清零,也就是你今天输入了1000次输对了997次,只输错了3次,那对不起,依然要锁定。而且输入错误的3次不一定要连续。只要三次输入错误三次就锁定。
2、关于计数和状态的保存我考虑还是通过文件来持久化保存,每次输入错误次数的累加和锁定都保存到文件中,这样虽然增加了文件的操作,但是保证了程序的可靠性,这样程序退出,计数依然有效。用来保存用户信息的文件结构如下所示

流程图:
设计思路有了,那么接下来就要把我们的思路和设计通过流程图的方式实现出来:流程图如下所示

代码实现:
#!/usr/bin/env python3
# coding:utf-8
'''
Created on: 2015年12月29日 @author: 张晓宇 Email: 61411916@qq.com Version: 1.0 Description: 输入用户名密码,认证成功显示欢迎信息,认证失败,输错三次后锁定 Help:
'''
import os
# 定义用户信息写入函数,用于把用户信息写回文件
def write_to_account_file(accounts, account_file_path):
account_file = open(account_file_path, 'w')
for key,val in accounts.items():
line = []
line.append(key)
line.extend(val)
print(' '.join(line))
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 = 1
status_col_num = 2
error_count_num = 3
app_info = '''
+-----------------------------------+
| Welcome to 65brother system |
| Version: 1.0 |
| Author: zhangxiaoyu |
+-----------------------------------+
'''
welcome_msg = 'Welcome %s, authentication is successful!'
# 判断账户文件是否存在
if os.path.exists(account_file_path):
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_file.close() flag = True
while flag:
print(app_info)
# 输入用户名
username = input('Username(Enter quit to exit): ').strip()
# 判断是否输入的是否为quit
if username == 'quit':
# 是则退出循环,程序结束
break
password = input('Password: ').strip()
# 判断用户名是否存在
if username not in accounts:
# 不存在提示错误信息并退出当前循环让用户重新输入
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)
break
else:
# 不正确
# 提示用户名或密码错误
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)
break
write_to_account_file(accounts, account_file_path)
代码说明:
1、这里用了两个今天课程没有讲的内容:字典和函数,将用户信息以字典的方式保存是出于判断用户名是否存在的考虑,读文件的时候直接将用户名作为字典的一个key,其他的信息作为字典的value与key一一对应,这样在判断用户名是否存在只需要通过in这个成员运算符进行判断就可以了
2、代码的第61和62两行代码完成的就是将文件变成字典的过程
account = line.strip().split() # 先把文件的每一行通过split方法将以空格分隔的用户信息转换成列表
accounts[account[0]] = account[1:] # 然后把列表的的一个元素作为字典的key,剩下的转换成为value,完成列表到字典的转换
转换成字典的过程大致的过程是这样的,如下图所示

我的Python成长之路---第一天---Python基础(作业1:登录验证)---2015年12月26日(雾霾)的更多相关文章
- 我的Python成长之路---第一天---Python基础(1)---2015年12月26日(雾霾)
2015年12月26日是个特别的日子,我的Python成之路迈出第一步.见到了心目中的Python大神(Alex),也认识到了新的志向相投的伙伴,非常开心. 尽管之前看过一些Python的视频.书,算 ...
- 我的Python成长之路---第一天---Python基础(作业2:三级菜单)---2015年12月26日(雾霾)
作业二:三级菜单 三级菜单 可一次进入各个子菜单 思路: 这个题看似不难,难点在于三层循环的嵌套,我的思路就是通过flag的真假来控制每一层的循环的,简单来说就是就是通过给每一层循环一个单独的布尔变量 ...
- 我的Python成长之路---第一天---Python基础(6)---2015年12月26日(雾霾)
七.列表——list Python的列表是一种内置的数据类型,是由Python的基本数据类型组成的有序的集合.有点类似C语言的数组,但与数组不同的是,Python在定义列表的时候不用指定列表的容积(长 ...
- 我的Python成长之路---第一天---Python基础(2)---2015年12月26日(雾霾)
三.数据类型 Python基本类型(能够直接处理的数据类型有以下几种)主要有5种 1.整数(int) Python可以处理任意大小的整数,当然包括负整数,在程序中的表示方法和数学上的写法一模一样,例如 ...
- 我的Python成长之路---第一天---Python基础(4)---2015年12月26日(雾霾)
五.数据运算与数据运算符 1.算术运算符 算术运算符 运算符 描述 示例 + 加法 >>> 14 - 5 9 - 减法 >>> 14 - 5 9 * 乘法 &g ...
- 我的Python成长之路---第一天---Python基础(5)---2015年12月26日(雾霾)
六.流程控制 与C语言不通的事Python的流程控制的代码块不是用{}花括号表示的,而是用强制缩进来,而且缩进必须一致,官方推荐是使用4个空格,不建议使用使用tab(制表符)做缩进,一是不同的系统ta ...
- 我的Python成长之路---第一天---Python基础(3)---2015年12月26日(雾霾)
四.变量和常量 变量是用来存储程序运行期间需要临时保存可以不断改变的数据的标识符.Python有自身的内存回收机制,所以在开发过程中不用考虑变量的销毁等 Python中的变量名命名有如下规则: 1.变 ...
- python成长之路第一篇(5)文件的基本操作
一.三元运算 我们在上章学习的if,,else,,有一种简便的方法 他的表达式是这样的:变量 = 值1 if 条件 else 值2 解释过来就是如果aaa等于sss则输出值1否则输出值2 二.类的概念 ...
- PYthon成长之路第一篇(1)__字符串初识
今天一起走进python的代码世界,一起领悟python的魅力 在很多学习python的书中都会以 print “Hello,world!” 这样的而一个程序为开始,那么其中的 hello,worl ...
随机推荐
- C#编辑基础笔记
目录 1. .NET .NET Framework是一种多语言的平台,一种技术. 而c#是基于其上面的一种语言. 1 2. Winform 桌面应用程序[从.net平台上面开发的 ...
- POJ 1458 Common Subsequence(LCS最长公共子序列)
POJ 1458 Common Subsequence(LCS最长公共子序列)解题报告 题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?c ...
- BZOJ 1651: [Usaco2006 Feb]Stall Reservations 专用牛棚( 线段树 )
线段树.. -------------------------------------------------------------------------------------- #includ ...
- Android 学习开发笔记《Android认识》
1. Android:2007年11月5日第一版,2009年5月豪华版,2010年HTC手机 2. Android框架主要:应用程序.应用程序框架.函数库.运行时. ...
- cocos2dx工程
1. create-android-project.sh 进入 pro.android/ ln -s ../Resources ./Resources
- linux下检测端口是否连通
检测tcp端口使用telnet命令 telnet 例:telnet 192.168.0.1 80 检测udp端口使用uc命令 uc -zu 例:uc -zu 192.169.0.1 80 以上命令 ...
- IT第七天 - 类及其属性、方法的理解,断点调试初识,代码优化总结,编程逻辑培养
IT第七天 上午 类 1.对象:是多个实体抽象出来的共同点集合,对象包括:属性(即实体的特征).方法(即尸体的功能作用) 2.程序中,用类来模拟对象 3.类是抽象的,是对象的类型,是将多个拥有相同属性 ...
- F#实现的单链表(函数式的思想)
// 在 http://fsharp.net 上了解有关 F# 的更多信息 // 请参阅“F# 教程”项目以获取更多帮助. type list = | Nil | Cons of int * list ...
- Internet Explorer 11(IE11)无法切换第三方输入法
Windows 8.1搭载了新的IE11版本,还发布了IE11 for Windows 7. IE11除了支持全尺寸Win设备以外,还比IE10更快速流畅,支持3D等高性能的浏览体验.全新F12开发者 ...
- L型代码结构案例:Link访问权限(上)
这是松结对编程的第20篇(专栏目录). 本文探讨Link访问权限的最佳实现方法,力求外观干净且封装良好. 这些代码将位于L型代码结构(参见松结对编程系列中的定义)的下层,调用者无需理解其原理. 顺便说 ...