16.flask-login

概念

Flask-Login 为 Flask 提供了用户会话管理。处理了日常的登入,登出并且长时间记住用户的会话。

会:

  • 在会话中存储当前活跃的用户 ID,让你能够自由地登入和登出。

  • 能够限制登入(或者登出)用户可以访问的视图。

  • 处理让人棘手的 “记住我” 功能。

  • 能够帮助保护用户会话免遭 cookie 被盗的牵连。

  • 可以与以后可能使用的 Flask-Principal 或其它认证扩展集成。

但是,不会:

  • 限制使用特定的数据库或其它存储方法。如何加载用户完全由你决定。

  • 限制使用用户名和密码,OpenIDs,或者其它的认证方法。

  • 处理超越 “登入或者登出” 之外的权限。

  • 处理用户注册或者账号恢复。

安装

pip install flask-login

配置

登录管理对象 login_managerlogin_view 属性,指定登录页面的视图函数 (登录页面的 endpoint),即验证失败时要跳转的页面,设置为登录页。

用户模块

构造数据

要做用户验证,需要维护用户记录,为了方便演示,使用一个全局列表 USERS 来记录用户信息,并且初始化了两个用户信息:

password 为登录密码,通过模块 werkzeug.security 提供了 generate_password_hash 方法,使用 sha256 加密算法将字符串变为密文。

不要在系统中存放用户密码的明文

基于用户信息,定义两方法,用来创建( create_user )和获取( get_user )用户信息:

用户类

下面创建一个用户类,类维护用户的登录状态,是生成 Session 的基础,Flask-Login 提供了用户基类 UserMixin,方便定义自己的用户类,定义一个 User

加载登录用户

有了用户类,并且实现了 get 方法,就可以实现 login_manageruser_loader 回调函数了,user_loader 的作用是根据 Session 信息加载登录用户,它根据用户 ID,返回一个用户实例:

登录页面

定义表单类

视图函数

  • 视图函数同时支持 GETPOST 方法

  • form.validate_on_submit() 可以判断用户是否完整的提交了表单,只对 POST 有效,所以可以用来判断请求方式

  • 如果是 POST 请求,获取提交数据,通过 get_user 方法查找是否存在该用户

  • 如果用户存在,则创建用户实体,并校验登录密码

  • 校验通过后,调用 login_user 方法创建用户 Session,然后跳转到请求参数中 next 所指定的地址或者首页 (不用担心如何设置 next,还记得上面设置的 login_manager.login_view = 'login' 吗? 对,未登录访问时,会跳转到 login,并且带上 next 查询参数)

  • POST 请求,或者未经过验证,会显示 login.html 模板渲染后的结果

模板

需要验证的页面

为了方便演示,将首页作为需要验证的页面,通过验证将看到登录者欢迎信息,页面上还有个登出链接

首页视图函数 index:

  • 注解 @login_required 会做用户登录检测,如果没有登录要方法此视图函数,就被跳转到 login 接入点( endpoint )。

  • current_user 是当前登录者,是 User 的实例,是 Flask-Login 提供全局变量( 类似于全局变量 g )。

  • username 是模板中的变量,可以将当前登录者的用户名传入 index.html 模板。

登出视图函数 logout:

  • 只有登录了才有必要登出,所以加上注解 @login_required。

  • logout_user 方法和 login_user 相反,由于注销用户的 Session

  • 登出视图不需要模板,直接跳转到登录页,实际项目中可以增加一个登出页,展示些有趣的东西。

用户注册

上面的演示了,已存在用户登录的情况,不存在用户需要完成注册才能登录。

注册功能和登录很类似,页面上多了密码确认字段,并且需要验证两次输入的密码是否一致,后台逻辑是:如果用户不存在,且通过检验,将用户数据保存到 USERS 列表中,跳转到 login 页面。

配合sqlalchemy使用

示范

直接让用户模型继承 flask.ext.login.UserMixin类,类中有上面4个方法的默认实现 如:

flask-sqlachemy和sqlchemy这里都一样:

Flask-Login要求实现一个回调函数,使用 get_id()方法返回的唯一标识用户的Unicode字符串 作为参数 返回这个用户对象.

如果是继承的UserMixin类, get_id()方法默认返回的用户的id. 如果用户不存在,应该返回None.

此外如果需要定制数据库的nid时,可在上方添加:

默认情况下是查看id的:如果数据库的user表的主键为id,则可不定制get_id()

flask-sqlachemy的语法如下:

获取当前登陆的用户,

也可以在模版中使用 `

` 判断

在模版中使用,如果用户已认证就显示他的名字

current_user.name的name是user表的name

如何控制Flask-Login的session过期时间

在 Flask-Login 中,如果不特殊处理的话,session 是在你关闭浏览器之后就失效的。也就是说每次重新打开页面都是需要重新登录的。

如果需要自己控制 session 的过期时间的话,

  • 首先需要设置 login_manager 的 session类型为永久的,

  • 然后再设置 session 的过期时间

还需要注意的是 cookie 的默认有效期:

使用redis存储session

跳转

最后更新于

这有帮助吗?