Flask[相逢]

Flask[相逢]

七月 06, 2023

表单

用户使用表单向服务器提交信息,例如最常见的登录。

那么如何在html页面里提交表单,以及flask如何处理表单数据?以及表单敏感信息如何存储。

HTML登录页面中的form表单

1
2
3
4
5
<form action="/login" method="POST">
<p>name: <input type="text" name="name" /></p>
<p>password: <input type="password" name="password" /></p>
<input type="submit" value="提交" />
</form>
  • action 设置提交的url
  • method 设置请求的方法
  • input标签的type设置为password时,在页面输入信息时不会显示明文

服务端接收表单信息的方式如下

1
2
3
4
5
6
7
8
9
10
11
@app.route('/login', methods=['GET', 'POST'])
def do_login():
if request.method == 'GET':
return render_template('login.html')
else:
name = request.form['name']
password = request.form['password']
if name == 'python':
return render_template('index.html', name=name)
else:
return redirect('/login')

通过request.form来获取表单信息,然后对用户输入的用户名和密码做校验。为了演示,这里省去了数据库查询的逻辑,简化了过程。

生产环境下,用户的密码也并不是明文存储,例子注册网站账号时,填写的密码是888888,网站不会明文存储这个密码,简易的方法为存储它的md5值

1
2
3
4
5
6
7
8
9
import hashlib
password = '888888'
bpwd = bytes(password, encoding='utf-8')

m = hashlib.md5()
m.update(bpwd)

md5_pwd = m.hexdigest()
print(md5_pwd)

888888的md5值是 21218cca77804d2ba1922c33e0151105,这样,即便你在数据库里看到这个数值,你也不知道它真实的密码是什么。

关于md5:md5并非加密算法,而是密码散列函数,它是一种单向函数,也就是说极其难以由散列函数输出的结果,回推输入的数据是什么,但是同一个值经过md5计算后的值是不会发生变化的。

这样,你只要记住21218cca77804d2ba1922c33e0151105是888888的md5值,就可以对user表进行撞库处理了。

关于网上所谓的md5解密,其实就是事先掌握了海量的密码和与之对应的md5值,然后通过md5反向查找原始密码。

md5值作为密码不够安全,你可以使用werkzeug.security模块里的generate_password_hash和check_password_hash函数。

generate_password_hash是密码加盐哈希函数,对同一个密码,每一次加密都会得到不同的值。generate_password_hash是密码验证函数,而并非计算出原始密码。

下面是一段示例代码

1
2
3
4
5
6
7
8
9
from werkzeug.security import generate_password_hash, check_password_hash

# 对密码进行加密
password = generate_password_hash("888888")
print(password)

# 检查密码是否正确
result = check_password_hash(password, '888888')
print(result)

多次运行你就会发现,每次得到的password都是不同的,但是check_password_hash都能正确验证。

使用这两个函数,就绝对能够防止破解了么?并非如此,黑客还是可以在得到user表后进行暴力破解,但是暴力破解的难度和成本都增加了。

888888经过generate_password_hash函数处理后,会得到无数种加密结果,因此,就无法维护一个加密结果与原始密码的映射表,当你拿到一个加密后的密码后,你当然可以使用check_password_hash(password, ‘888888’)来判断这个密码是不是888888加密后的结果。