10.注册和登录功能实现(3)—— 注册数据写入数据库

现在数据获取到了,提示也有了,我们需要把注册的数据写入到数据库,这一步很简单,直接使用之前提到过的方法,但是我们不能直接把明文密码写入到数据库中,那样做是十分不安全的,我们需要将其加密之后再写进去,具体是用到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这个装饰器,以及 sessiong对象的区别。

那么同样的,登录的验证过程,就不能直接去拿数据库加密过的哈希和原始的密码对比了,我们用werkzeug.securitycheck_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')

你可能感兴趣的:(pythonflask)