这几天学了MySQLdb的操作,觉得意犹未尽,python也已经学了有段时间,所以考虑着通过与数据库的集成,写一个简单的登陆、注册和更改密码的系统。
最终代码是写了一百二十多行,基本的功能已经实现,就是界面不太友好,下一步是打算学一些GUI的库,完善界面。
写这个系统的初衷,源于在廖雪峰老师的网站上http://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/0013868328251266d86585fc9514536a638f06b41908d44000
接触到的hashlib内建库,觉得非常有意思,在接下来的记录里,大家可以看到是如何被使用的
import MySQLdb import hashlib |
这个比较简单,第一个库是操纵MySQL数据库的,第二个库里有哈希算法(哈希算法将任意长度的二进制值映射为较短的固定长度的二进制值,这个小的二进制值称为哈希值。)
两者编写的原则都是"高内聚,低耦合",这些我也是刚体会到,理解的也不深
建立这个函数的思路就是,将用户输入的username和password插入到数据库里,这里尤为需要注意的是,存储的密码是经过特殊处理的,说白了其实就是哈希值,这样就保证了即使有人在后台可以看到数据库或者说被黑客恶意攻击,用户的密码也是安全的。
def Register(username, password): # 调用hashlib里的方法,生成哈希值 md5 = hashlib.md5() # 这个属于'加盐',就是让哈希值更复杂,不易破解 # 廖老师的那篇文章里讲的很详细 md5.update(password + 'wpy' + username) md = md5.hexdigest() # 生成哈希值 realpassword = md
# insert进数据库 sql = "INSERT INTO LOGIN(USERNAME, PASSWORD) VALUES('%s', '%s')" % (username, realpassword) try: cursor.execute(sql) # 必须commit,否则数据库不会更新 db.commit() except: db.rollback() |
要注意的是,存储在数据库里的password其实经过特殊处理的,所以在验证的时候,也要先将用户输入的password用相同的方法转换成哈希值,然后再比较
def Login(username, password): # 与Register()里生成哈希值的方法一样 md5 = hashlib.md5() md5.update(password + 'wpy' + username) md = md5.hexdigest() realpassword = md
sql = "SELECT PASSWORD FROM LOGIN WHERE USERNAME = '%s'" % (username) cursor.execute(sql) # username是主键,至多有一条纪录 pwd = cursor.fetchone()[0] # 返回布尔值 if pwd == realpassword: return True else: return False |
def Update(username, password):
md5 = hashlib.md5() md5.update(password + 'wpy' + username) md = md5.hexdigest() realpassword = md
sql = "UPDATE LOGIN SET PASSWORD = '%s' WHERE USERNAME = '%s'" %(realpassword, username) try: cursor.execute(sql) db.commit() except: db.rollback() |
- 在Register的时候,要验证输入的username是否已经存在,已经存在的话要允许用户重新输入,简单的说要有一个循环来控制
- 在Login的时候,一要先检查username是否存在(这个不是必要的,即也可以不验证),二是如果用户密码输入错误的话可以再次输入,但次数要限制,不能超过五次
- 在Update的时候,用户要首先验证自己的身份,就是说要先输入原先的username和password,正确的话才能执行Update
看代码
初始化 //数据库连接,新建Table
db = MySQLdb.connect("localhost", "(username)", "(password)", "testdb") cursor = db.cursor() cursor.execute("CREATE TABLE LOGIN(USERNAME VARCHAR(20) PRIMARY KEY, PASSWORD VARCHAR(40))") |
循环主体 //比较复杂,大部分时间都花在这里
# 最外面的一层循环,控制系统的结束 while True: # 根据用户的输入,决定系统是否终止 start = raw_input("You want to (R)egister or (L)ogin or (U)pdate?") # 判断 if start.lower() == 'r':
while True: #用户可以输入多次username username = raw_input("Please input your new name:") sql = "SELECT PASSWORD FROM LOGIN WHERE USERNAME = '%s'" % username # 查询不到结果返回None m = cursor.execute(sql) if m: print "'%s' has already existed.Please change your name." % username # 输入错误的话重新循环 continue else: password = raw_input("Please input your password:") Register(username, password) print "Register sucessfully!" # while循环中断的唯一途径 break
elif start.lower() == 'l':
while True: # 顶层循环,控制用户名的输入 username = raw_input("Please input your name:") sql = "SELECT PASSWORD FROM LOGIN WHERE USERNAME = '%s'" % username m = cursor.execute(sql) if not m: print "'%s' doesn't exist.Please change your name." % username continue else: # 第二层循环,控制密码输入的次数 for i in range(5): password = raw_input("Please input your password:") if Login(username, password): print "Login sucessfully!" # 密码正确,及时跳出循环 break else: print "The password is wrong.Please input again." # 循环正常结束的话,执行该else语句 else: print "You have tried 5 times. The system is locked." # 跳出顶层循环 break
elif start.lower() == 'u':
while True: username = raw_input("Please input your name:") sql = "SELECT PASSWORD FROM LOGIN WHERE USERNAME = '%s'" % username m = cursor.execute(sql) if not m: print "'%s' doesn't exist.Please change your name." % username continue else: for i in range(5): # 先输入原始密码 oldpassword = raw_input("Please input your old password:") # 原始密码正确的话输入新密码 if Login(username, oldpassword): password = raw_input("Please input your new password:") Update(username, password) print "Update sucessfully!" # 及时跳出循环 break else: print "The password is wrong.Please input again." else: print "You have tried 5 times. The system is locked."
break # 大循环终止条件 else: break
print "The system is closed!" cursor.close() db.close() |
结束!!!!!!!!
结果如下
总结:这个系统,实现起来并不算难,代码量也不多,一百多行,算是一次有益的尝试,以前没有做过,感觉还挺有意思的。逻辑思路并不复杂,但是要理清楚,先把系统的结构大体构件,再去填充,一边写一边想的话,效率太低。真正的总结的话,其实是:一定要学GUI!!!!