登录、退出

python flask
创建于:2019年07月02日

模型类User.py中定义验证密码方法

from app import db
import hashlib

class User(db.Model):
    __tablename__ = 'user'
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(10), unique=True)
    password = db.Column(db.String(64))

def __init__(self, username, password):
    self.username = username
    self.password = self.set_password(password)

def check_password(self, pwd, bcrypt_password):
    password = self.set_password(pwd)
    return bcrypt_password == password

def set_password(self, pwd):
    md5 = hashlib.md5()
    if isinstance(pwd, str):
        pwd = pwd.encode('utf-8')
    md5.update(pwd)
    return md5.hexdigest()

控制器类Login.py

session方法

from app.admin import admin
from app.admin.model.User import User
from flask import render_template, redirect, url_for, session, request, flash
from app.admin.forms import LoginForm

#登录
@admin.route('/login', methods=['POST', 'GET'])
def login():
    form = LoginForm()
    if request.method == 'POST' and form.validate_on_submit():
        data = form.data
        user = User.query.filter_by(username=data['account']).first()
        if user is not None:
            if user.check_password(data['password'], user.password):
                session['userid'] = user.id
                return redirect(url_for('admin.index'))
            flash('密码错误')
        return redirect(url_for('admin.index'))
    return render_template('/admin/login.html', form = form)

#退出

@admin.route('/logout', methods=['GET'])
def logout():
    session.pop('userid', None)
    return redirect(url_for('admin.login'))

当用户输入了正确的口令登录成功后,服务器可以从数据库取到用户的id,并按照如下方式计算出一个字符串:

"用户id" + "过期时间" + SHA1("用户id" + "用户口令" + "过期时间" + "SecretKey")

当浏览器发送cookie到服务器端后,服务器可以拿到的信息包括:

  • 用户id
  • 过期时间
  • SHA1值

如果未到过期时间,服务器就根据用户id查找用户口令,并计算:

SHA1("用户id" + "用户口令" + "过期时间" + "SecretKey")

在配置文件中设置cookie密钥、名称和过期时间

_COOKIE_KEY = '\xfd{H\xe5<\x95\xf9\xe3\x96.5\xd1\x01O<!\xd5\xa2\xa0\x9fR"\xa1\xa8'
COOKIE_NAME = 'flaskcookie'
EXPIRES = 86400

在控制器初始化文件中定义cookie生成函数

from app import app
import time, hashlib
def create_cookie(user):
    expires = str(int(time.time() + app.config['EXPIRES']))
    s = '%s-%s-%s-%s' % (user.id, user.password, expires, _COOKIE_KEY)
    L = [user.id, expires, hashlib.sha1(s.encode('utf-8')).hexdigest()]
    return '-'.join(L)

控制器Login.py

from app.admin import admin
from app.admin.model.User import User
from flask import render_template, redirect, url_for, request, make_response
from app import app
from app.admin.controller import create_cookie

#登录
@admin.route('/login', methods=['POST', 'GET'])
def login():
    if request.method == 'POST':
        user = request.get_json()
        username = user.get('username')
        password = user.get('password')
        user = User.query.filter_by(username=username).first()
        if user is not None:
            if user.check_password(password, user.password):
                cookie_value = create_cookie(user)
                response = make_response(jsonify(ajax(1, 'success')))
                response.set_cookie(app.config['COOKIE_NAME'], cookie_value)
                return response
            return jsonify(ajax(0, '密码错误'))
        return jsonify(ajax(0, '账号不存在'))
    return render_template('admin/login.html')

在控制器初始化文件中定义cookie处理函数

from flask import request
from app import app
import time, logging
from app.admin.models.User import User

def check_cookie():
    cookie_str = request.cookies.get(app.config['COOKIE_NAME'])
    try:
        L = cookie_str.split('-')
        if len(L) != 3:
            return None
        uid, expires, sha1 = L
        if int(expires) < time.time():
            return None
        user = User.query.get(uid)
        if user is None:
            return None
        s = '%s-%s-%s-%s' % (uid, user.passwd, expires, app.config['_COOKIE_KEY'])
        if sha1 != hashlib.sha1(s.encode('utf-8')).hexdigest():
            logging.info('invalid sha1')
            return None
        user.passwd = '******'
        return user
    except Exception as e:
        logging.exception(e)
        return None

退出

@admin.route('/logout', methods=['GET'])
def logout():
    response = make_response(render_template('admin/login.html'))#退出后跳转页面
    response.set_cookie(app.config['COOKIE_NAME'], '-delete-')
    return response