• Flask 扩展 用户会话


    pip install flask-login

    接下来创建扩展对象实例:

    from flask import Flask
    from flask_login import LoginManager
     
    app = Flask(__name__)
    login_manager = LoginManager(app)

    同时,你可以对LoginManager对象赋上配置参数:

    # 设置登录视图的名称,如果一个未登录用户请求一个只有登录用户才能访问的视图,
    # 则闪现一条错误消息,并重定向到这里设置的登录视图。
    # 如果未设置登录视图,则直接返回401错误。
    login_manager.login_view = 'login'
    # 设置当未登录用户请求一个只有登录用户才能访问的视图时,闪现的错误消息的内容,
    # 默认的错误消息是:Please log in to access this page.。
    login_manager.login_message = 'Unauthorized User'
    # 设置闪现的错误消息的类别
    login_manager.login_message_category = "info"

    编写用户类

    使用Flask-Login之前,你需要先定义用户类,该类必须实现以下三个属性和一个方法:

    属性 is_authenticated

      当用户登录成功后,该属性为True。

    属性 is_active

      如果该用户账号已被激活,且该用户已登录成功,则此属性为True。

    属性 is_anonymous

      是否为匿名用户(未登录用户)。

    方法 get_id()

      每个用户都必须有一个唯一的标识符作为ID,该方法可以返回当前用户的ID,这里ID必须是Unicode。

    因为每次写个用户类很麻烦,Flask-Login提供了”UserMixin”类,你可以直接继承它即可:

    from flask_login import UserMixin
     
    class User(UserMixin):
        pass

    从会话或请求中加载用户

    在编写登录登出视图前,我们要先写一个加载用户对象的方法。它的功能是根据传入的用户ID,构造一个新的用户类的对象。为了简化范例,我们不引入数据库,而是在列表里定义用户记录。

    # 用户记录表
    users = [
        {'username': 'Tom', 'password': '111111'},
        {'username': 'Michael', 'password': '123456'}
    ]
     
    # 通过用户名,获取用户记录,如果不存在,则返回None
    def query_user(username):
        for user in users:
            if user['username'] == username:
                return user
     
    # 如果用户名存在则构建一个新的用户类对象,并使用用户名作为ID
    # 如果不存在,必须返回None
    @login_manager.user_loader
    def load_user(username):
        if query_user(username) is not None:
            curr_user = User()
            curr_user.id = username
            return curr_user

    上述代码中,通过”@login_manager.user_loader”装饰器修饰的方法,既是我们要实现的加载用户对象方法。它是一个回调函数,在每次请求过来后,Flask-Login都会从Session中寻找”user_id”的值,如果找到的话,就会用这个”user_id”值来调用此回调函数,并构建一个用户类对象。因此,没有这个回调的话,Flask-Login将无法工作。

    有一个问题,启用Session的话一定需要客户端允许Cookie,因为Session ID是保存在Cookie中的,如果Cookie被禁用了怎么办?那我们的应用只好通过请求参数将用户信息带过来,一般情况下会使用一个动态的Token来表示登录用户的信息。此时,我们就不能依靠”@login_manager.user_loader”回调,而是使用”@login_manager.request_loader”回调。

    from flask import request
     
    # 从请求参数中获取Token,如果Token所对应的用户存在则构建一个新的用户类对象
    # 并使用用户名作为ID,如果不存在,必须返回None
    @login_manager.request_loader
    def load_user_from_request(request):
        username = request.args.get('token')
        if query_user(username) is not None:
            curr_user = User()
            curr_user.id = username
            return curr_user

    为了简化代码,上面的例子就直接使用用户名作为Token了,实际项目中,大家还是要用一个复杂的算法来验证Token。

    登录及登出

    一切准备就绪,我们开始实现登录视图:

    from flask import render_template, redirect, url_for, flash
    from flask_login import login_user
     
    @app.route('/login', methods=['GET', 'POST'])
    def login():
        if request.method == 'POST':
            username = request.form.get('username')
            user = query_user(username)
            # 验证表单中提交的用户名和密码
            if user is not None and request.form['password'] == user['password']:
                curr_user = User()
                curr_user.id = username
     
                # 通过Flask-Login的login_user方法登录用户
                login_user(curr_user)
     
                # 如果请求中有next参数,则重定向到其指定的地址,
                # 没有next参数,则重定向到"index"视图
                next = request.args.get('next')
                return redirect(next or url_for('index'))
     
            flash('Wrong username or password!')
        # GET 请求
        return render_template('login.html')

    上述代码同之前Login视图最大的不同就是你在用户验证通过后,需要调用Flask-Login扩展提供的”login_user()”方法来让用户登录,该方法需传入用户类对象。这个”login_user()”方法会帮助你操作用户Session,并且会在请求上下文中记录用户信息。另外,在具体实现时,建议大家对”next”参数值作验证,避免被URL注入攻击。

    “login.html”模板很简单,就是显示一个用户名密码的表单:

    <!doctype html>
    <title>Login Sample</title>
    <h1>Login</h1>
    {% with messages = get_flashed_messages() %}
        <div>{{ messages[0] }}</div>
    {% endwith %}
    <form action="{{ url_for('login') }}" method="POST">
        <input type="text" name="username" id="username" placeholder="Username"></input>
        <input type="password" name="password" id="password" placeholder="Password"></input>
        <input type="submit" name="submit"></input>
    </form>

    接下来,让我们写个index视图

    from flask_login import current_user, login_required
     
    @app.route('/')
    @login_required
    def index():
        return 'Logged in as: %s' % current_user.get_id()

    装饰器”@login_required”确保只有登录用户才能访问这个index视图,Flask-Login帮我们实现了这个装饰器。如果用户未登录,它就会将页面重定向到登录视图,也就是我们在第一节中配置的”login_manager.login_view”的视图。

    同时,重定向的地址会自动加上”next”参数,参数的值是当前用户请求的地址,这样,登录成功后就会跳转回当前视图。可以看到我们对于用户登录所需要的操作,这个装饰器基本都实现了

    Flask-Login还提供了”current_user”代理,可以访问到登录用户的用户类对象。我们在模板中也可以使用这个代理。让我们再写一个home视图:

  • 相关阅读:
    腾讯课堂——基础数据类型(dict字典)
    腾讯课堂——基础数据类型(tuple元祖)
    基础数据类型(list列表)
    第 018讲:函数:灵活即强大(关键字函数,默认函数,收集函数)
    第 015讲:字符串:格式化
    第 013讲: 元组tuple 上了枷锁的列表
    第 012讲:打了激素的数组3
    第 011讲:一个打了激素的数组[02]
    range函数的用法
    第 010讲:一个打了激素的数组[01]
  • 原文地址:https://www.cnblogs.com/Erick-L/p/7057694.html
Copyright © 2020-2023  润新知