现在数据获取到了,提示也有了,我们需要把注册的数据写入到数据库,这一步很简单,直接使用之前提到过的方法,但是我们不能直接把明文密码写入到数据库中,那样做是十分不安全的,我们需要将其加密之后再写进去,具体是用到werkzeug.security
中的generate_password_hash
这个函数,将字符串变成hash
值。
我们可以在User
模型中重写__init__
函数(或__setattr__
),当传入password
自动调用generate_password_hash
进行加密,如:
class Users(db.Model):
__tablename__ = 'users_info'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
username = db.Column(db.String(32), nullable=False)
password = db.Column(db.String(100), nullable=False)
register_time = db.Column(db.DateTime, nullable=False, default=datetime.now())
avatar_path = db.Column(db.String(256), nullable=False, default='images/doraemon.jpg')
def __init__(self, *args, **kwargs):
self.username = kwargs.get('username')
self.password = generate_password_hash(kwargs.get('password'))
这样每添加一个新用户,在init
的时候就自动把密码转为hash
值了,但是后续我们还得增加修改密码的功能,所以就直接简单点,在收到POST
数据的时候就把密码加密,然后存入数据库中,此时注册的视图函数代码如下:
from flask import Flask, render_template, request, flash, redirect, url_for
from models import db, Users
from werkzeug.security import generate_password_hash
from exts import validate
import config
...
@app.route('/register/', methods=['GET', 'POST'])
def register():
if request.method == 'GET':
return render_template('register.html')
else:
username = request.form.get('username')
password1 = request.form.get('password1')
password2 = request.form.get('password2')
message = validate(username, password1, password2)
flash(message)
if '成功' in message:
new_user = Users(username=username, password=generate_password_hash(password1))
db.session.add(new_user)
db.session.commit()
return redirect(url_for('login'))
else:
return render_template('register.html')
这里获取登录或注册成功的状态,使用了上一篇文章结尾说的方法,简化了代码量。
实际上更简单的方法是,我们直接对传入的{{ message }}
进行判断,如果带有'成功'
字符串,就显示蓝色,否则就显示红色。上文主要是为了说明@app.context_processor
这个装饰器,以及session
和g
对象的区别。
那么同样的,登录的验证过程,就不能直接去拿数据库加密过的哈希和原始的密码对比了,我们用werkzeug.security
的check_password_hash
方法,它能验证哈希值是否与原始的密码是匹配的,然后修改validate
函数如下:
from models import Users
from werkzeug.security import check_password_hash
def validate(username, password1, password2=None):
user = Users.query.filter(Users.username == username).first()
if password2:
if user:
return '用户名已经存在'
else:
if len(username) < 4:
return '用户名长度至少4个字符'
elif password1 != password2:
return '两次密码不一致'
elif len(password1) < 6:
return '密码长度至少6个字符'
else:
return '注册成功,请登录'
else:
if user:
if check_password_hash(user.password, password1):
return '登录成功'
else:
return '密码错误'
else:
return '用户名不存在'
登录页面的视图函数如下:
@app.route('/login/', methods=['GET', 'POST'])
def login():
if request.method == 'GET':
return render_template('login.html')
else:
username = request.form.get('username')
password = request.form.get('password')
message = validate(username, password)
if '成功' in message:
return redirect(url_for('home'))
else:
flash(message)
return render_template('login.html')