Flask——登入、退出

codelife發表於2019-08-24

模型類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'))

cookie 版

當使用者輸入了正確的口令登入成功後,伺服器可以從資料庫取到使用者的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
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章