flask-login扩展进行会话管理

用户会话管理

Flask-Login

文档

这个扩展提供了日常的登入、登出、记住会话的操作。

安装

pip install Flask-Login

使用

配置

创建一个登录管理器LoginManager

from flask import Flask
from flask_login import LoginManager
from config import config

app = Flask(__name__)

#添加配置信息
app.config.from_object(config.get('production'))

# 登录模块初始化
login = LoginManager(app)
# 登录限制,不通过时跳转到登录视图
login.login_view = 'main.login'
# 自定义未登录提示信息
login.login_manager = u'请先登录'

必要条件

from flask_login import current_user
from App import app,login
from App import app,login
from .models import db,User

# 从session里读取用户信息
# 接受一个Unicode ID作为参数
@login.user_loader
def load_user(id):
    return User.query.get(int(id))

# 请求前的钩子
@app.before_request
def before_request():
    g.user = current_user
    if g.user.is_authenticated:
        g.user.last_seen = datetime.now()
        db.session.add(g.user)
        db.session.commit()

而我们的用户表类,需要实现如下属性和方法,可以继承UserMixin它提供了默认的设置。

is_authenticated
is_active
is_anonymous
get_id()

通常用户的密码是不明文存储的,我们通过hash方法简单实现密码的散列存储。

from . import db
from werkzeug.security import generate_password_hash,check_password_hash
from flask_login import UserMixin

class User(UserMixin,db.Model):
    __tablename__ = 'user'

    id = db.Column(db.Integer,primary_key=True)
    name = db.Column(db.String(64),index=True,unique=True)
    email = db.Column(db.String(120),index=True,unique=True)
    password_hash = db.Column(db.String(128))
    last_seen = db.Column(db.DateTime)
    avatar = db.Column(db.String(256))
    posts = db.relationship('Post',backref='post_user',lazy='dynamic')
    comments = db.relationship('Comment',backref='comment_user',lazy='dynamic')
    articles = db.relationship('Article',backref='article_user',lazy='dynamic')

    # 通过验证
    def is_authenticated(self):
        return True
	# 已激活
    def is_active(self):
        return True
	# 匿名用户
    def is_anonymous(self):
        return False
	# 获取user id
    def get_id(self):
        return self.id

    def set_password(self,password):
        self.password_hash = generate_password_hash(password)

    def check_password(self,password):
        return check_password_hash(self.password_hash,password)

    def __repr__(self):
        return f'user:{self.user_name}'

登录的视图实现

@main.route('/login',methods=['GET','POST'])
def login():
    # 判断当前用户是否验证,如果通过验证,返回首页
    if current_user.is_authenticated:
        return redirect(url_for('main.home'))
    # 创建一个表单实例
    form = LoginForm()
    if form.validate_on_submit():
        # 根据表格里的数据进行查询,查询到返回user对象,否则返回none
        user = User.query.filter_by(email=form.email.data).first()
        # 判断用户存在或者密码正确
        if not user:
            flash("未注册用户")
            return redirect(url_for('main.login'))
        if not user.check_password(form.password.data):
            flash("密码错误")
            return redirect(url_for('main.login'))
        # 登录成功保存是否记住密码状态
        login_user(user,remember=form.remember_me.data)
        flash("登录成功")
        # 记录跳转至登录页的地址
        next_page = request.args.get('next')
        # 记录的地址不存在返回首页
        if not next_page or url_parse(next_page).netloc !='':
            next_page = url_for('main.home')
        return redirect(next_page)    
    return render_template(
        'login.html',
        title='Login',
        form=form,
        year=datetime.now().year
    )

模版引用登录状态

我们在模版里可以通过使用来进行一些未登录模版的渲染等。

{% if current_user.is_authenticated() %}
  Hi {{ current_user.name }}!
{% endif %}


奖励一下