0%

Python练习册:0021

题目

    通常,登陆某个网站或者 APP,需要使用用户名和密码。密码是如何加密后存储起来的呢?请使用 Python 对密码加密。

分析

用户密码的存储与Python示例中,已经给出了解答,想要安全的存储密码至少需要把密码拼接随机salt后,存储sha256计算后的密文到数据库,这里我们存到sqlite3数据库中,做个示例。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
import os
import hashlib
import sqlite3
import binascii


#加密
def encrypt_passwd(passwd, salt=None):
#把8位随机内容,转成16进制输出作为salt
if salt is None:
salt = binascii.b2a_hex(os.urandom(8))
passwd = passwd.encode('utf-8')
#用hashlib自带函数,sha256,迭代10000次,生成哈希值
result = hashlib.pbkdf2_hmac('sha256', passwd, salt, 10000)

#返回salt和密文
return salt + binascii.b2a_hex(result)


#验证
def verify_passwd(salthash, passwd):
if isinstance(salthash, str):
salthash = salthash.encode('utf-8')

#验证是否一致
return encrypt_passwd(passwd, salt=salthash[:16]) == salthash


#初始化sqllite3数据库
def init_db():

conn = sqlite3.connect("user.db")
c = conn.cursor()
c.execute("DROP TABLE IF EXISTS USER;")
sql = """CREATE TABLE USER(
ID INTEGER PRIMARY KEY autoincrement,
USERNAME TEXT NOT NULL,
PASSWORD TEXT NOT NULL);
"""
c.execute(sql)
conn.commit()
return conn


#注册新用户
def register(conn, username, passwd):
c = conn.cursor()
#加密
passwd = encrypt_passwd(passwd).decode('utf-8')

#写入到数据库
c.execute("INSERT INTO USER (ID,USERNAME,PASSWORD) VALUES (NULL,?,?)",
(username, passwd))
conn.commit()
print("注册%s成功!" % (username))


#登录
def sgin(conn, username, passwd):
c = conn.cursor()
cur = c.execute("SELECT PASSWORD from USER where USERNAME=:name",
{"name": username})
#获取密码
pwd = cur.fetchone()
#验证用户是否存在,并验证密码
if pwd and verify_passwd(pwd[0], passwd):
print('登录%s成功!' % (username))
return True
else:
print("登录%s失败" % (username))
return False


if __name__ == '__main__':
c = init_db()
register(c, "zhang3", "123456")
register(c, "li4", "212")
sgin(c, "zhang3", "1234")
sgin(c, "li", "12")
while True:
user = input("user:")
passwd = input("passwd:")
if sgin(c, user, passwd):
break
c.close()

扩展

还有一个极端的选择是系统完全不接触密码,用户的身份认证转交受信任的第三方来处理。例如 OpenID 这样的解决方案。系统向受信任的第三方求证用户身份的合法性,用户通过密码向第三方证明自己的身份。比如腾讯开放平台

参考

欢迎关注我的其它发布渠道