用户登录功能是 Web 系统一个基本功能,是为用户提供更好服务的基础,在 Flask 框架中怎么做用户登录功能呢?今天学习一下 Flask 的用户登录组件 Flask-Login

Python 之所以如此强大和流行,除了本身易于学习和功能丰富之外,最重要的是因为各种类库和组件,可以说没有 Python 做不了的事情,只有不知道的组件。

之所以选择 Flask-Login,是因为它基于Session,适合做有 UI 交互的用户登录,用我们学习了的 Flask 表单做演示,更容易理清用户登录的流程

用户登录说明

Flask-Login 和其他 Flask 组件并没有太大区别,有必要开始之前了解下用户登录的步骤:

登录:用户提供登录凭证(如用户名和密码)提交给服务器

建立会话:服务器验证用户提供的凭证,如果通过验证,则建立会话( Session ),并返回给用户一个会话号( Session id )

验证:用户在后续的交互中提供会话号,服务器将根据会话号( Session id )确定用户是否有效

登出:当用户不再与服务器交互时,注销与服务器建立的会话

依据以上步骤,我们设计一个应用场景,作为实现:

提供一个主页,需要登录才能访问

如果没有登录,跳转到登录页面,登录成功再跳回

登录成功后,可以点击登出退出登录

在登录页面提供注册连接,点击后跳转到注册页面

注册完成后,跳转到登录页面

初始化

先实例化 login_manager 对象,然后用它来初始化应用:

from flask importFlaskfrom flask_login importLoginManager#...

app = Flask(__name__) #创建 Flask 应用

app.secret_key= 'abc' #设置表单交互密钥

login_manager= LoginManager() #实例化登录管理对象

login_manager.init_app(app) #初始化应用

login_manager.login_view = 'login' #设置用户登录视图函数 endpoint

表单交互时,所以要设置secret_key,以防跨域攻击( CSRF )

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

用户模块

用户数据

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

from werkzeug.security importgenerate_password_hash#...

USERS =[

{"id": 1,"name": 'lily',"password": generate_password_hash('123')

},

{"id": 2,"name": 'tom',"password": generate_password_hash('123')

}

]

用户信息只包含最基本的信息:

name 为登录用户名

password 为登录密码,切忌:无论如何不要在系统中存放用户密码的明文,幸运的是模块 werkzeug.security 提供了 generate_password_hash 方法,使用 sha256 加密算法将字符串变为密文

id 为用户识别码,相当于主键

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

from werkzeug.security importgenerate_password_hashimportuuid#...

defcreate_user(user_name, password):"""创建一个用户"""user={"name": user_name,"password": generate_password_hash(password),"id": uuid.uuid4()

}

USERS.append(user)defget_user(user_name):"""根据用户名获得用户记录"""

for user inUSERS:if user.get("name") ==user_name:returnuserreturn None

create_user 接受用户名和密码,创建用户记录,对密码明文进行加密,并添加用户 ID (使用 uuid 模板的 uuid4方法生成一个全球唯一码),存储到 USERS 列表中

get_user 接受用户名,从 USERS 列表中查找用户记录,没有返回空

用户类

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

from flask_login import UserMixin #引入用户基类

from werkzeug.security importcheck_password_hash#...

classUser(UserMixin):"""用户类"""

def __init__(self, user):

self.username= user.get("name")

self.password_hash= user.get("password")

self.id= user.get("id")defverify_password(self, password):"""密码验证"""

if self.password_hash isNone:returnFalsereturncheck_password_hash(self.password_hash, password)defget_id(self):"""获取用户ID"""

returnself.id

@staticmethoddefget(user_id):"""根据用户ID获取用户实体,为 login_user 方法提供支持"""

if notuser_id:returnNonefor user inUSERS:if user.get('id') ==user_id:returnUser(user)return None

实例化方法接受一个用户记录,即 USERS 列表中的一个元素,用来初始化成员变量

get_id 方法返回用户实例的 ID,这是必须实现的,不然 Flask-Login 将无法判断用户是否被验证

get 是个静态方法,即可以通过类之间调用,是为了在获取验证后的用户实例时用的,必须接受参数 ID,返回ID 所以对应的用户实例

verify_password 方法接受一个明文密码,与用户实例中的密码做校验,将被用在用户验证的判断逻辑中

加载登录用户

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

@login_manager.user_loader #定义获取登录用户的方法

defload_user(user_id):return User.get(user_id)

登录页面

页面包括后台和展现(可以理解成前台)两部分

from wtforms importStringField, PasswordFieldfrom wtforms.validators importDataRequired, EqualTo#...

classLoginForm(FlaskForm):"""登录表单类"""username= StringField('用户名', validators=[DataRequired()])

password= PasswordField('密码', validators=[DataRequired()])

定义用户名和密码两个字段,分别是字符类型字段和密码类型字段,密码类型字段会在页面上显示为密码形式,以提高安全性

为两个字段设置必填规则

然后定义一个用户登录的视图函数 login:

from flask importrender_template, redirect, url_for, requestfrom flask_login importlogin_user#...

@app.route('/login/', methods=('GET', 'POST')) #登录

deflogin():

form=LoginForm()

emsg=Noneifform.validate_on_submit():

user_name=form.username.data

password=form.password.data

user_info= get_user(user_name) #从用户数据中查找用户记录

if user_info isNone:

emsg= "用户名或密码密码有误"

else:

user= User(user_info) #创建用户实体

if user.verify_password(password): #校验密码

login_user(user) #创建用户 Session

return redirect(request.args.get('next') or url_for('index'))else:

emsg= "用户名或密码密码有误"

return render_template('login.html', form=form, emsg=emsg)

分析下视图函数的逻辑:

视图函数同时支持 GET 和 POST 方法

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

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

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

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

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

前台

在 templates 模板下创建登录页面的模板 login.html:

{% macro render_field(field) %}

{{ field.label }}:{{ field(**kwargs)|safe }}

{% if field.errors %}

  • {% for error in field.errors %}
  • {{ error }}{% endfor %}

{% endif %}{% endmacro %}{{ form.csrf_token }}

{{ render_field(form.username) }}

{{ render_field(form.password) }}

{% if emsg %}

{{ emsg }}

{% endif %}

render_field 是 Jinja2 模板引擎的宏,接受表单字段将其渲染成 Html 代码,并格式化错误信息

emsg 错误信息单独做了处理,如果存在会显示出来

form 中并没有 action 属性,默认为当前路径

需要验证的页面

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

首页视图函数 index:

from flask importrender_template, url_forfrom flask_login importcurrent_user, login_required#...

@app.route('/') #首页

@login_required #需要登录才能访问

defindex():return render_template('index.html', username=current_user.username)

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

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

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

首页模板 index.html:

欢迎 {{ username }}!

登出

登出视图函数 logout:

from flask importredirect, url_forfrom flask_login importlogout_user#...

@app.route('/logout') #登出

@login_requireddeflogout():

logout_user()return redirect(url_for('login'))

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

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

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

小试牛刀

终于可以试试了,加上启动代码:

if __name__ == '__main__':

app.run(debug=True)

启动项目,如果一切正常将看到类似的反馈:

python app.py* Serving Flask app "app"(lazy loading)*Environment: production

WARNING: Thisis a development server. Do not use it ina production deployment.

Use a production WSGI server instead.*Debug mode: on*Restarting with stat* Debugger isactive!* Debugger PIN: 176-611-251

* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

访问 localhost:5000,将看到登录页,主要浏览器地址上的 next 查询参数:

填写正确的用户名和密码,点击登录,将进入首页:

用户注册

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

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

关于具体实现这里不做详细讲解了,本节代码示例中有实现,可以参考。

Flask-Login 其他特性

上面的实例中使用了一些 Flask-Login 的基本特性,Flask-Login 还提供了一些其他重要特性

记住我

记住我,并不是用户登出之后,再次登录时自动填写用户名和密码(这是浏览器的功能),而是在用户意外退出后(比如关闭浏览器)不用再次登录。

如果用户本地的 cookie 失效了,Flask-Login 会自动将用户 Session 放入 cookie中。

开启方法是将 login_user 方法的命名参数 remember 设置为 True,此功能默认是关闭的

Session 防护

Session 信息一般存放在 cookie 中,但是 cookie 不够安全,容易被窃取其中 Session 信息,伪造用户登录系统,幸运的是 Flask-Login 提供了 Session 防护机制,提供有 basic 和 strong 两种保护等级,通过 login_manager.session_protection 来开关和设置等级,默认等级为 basic,如果设置为 None 将关闭 Session 防护机制。

在保护机制开启的情况下,每次请求会根据用户的特征(一般指有用户IP、浏览器类型生成的哈希码)与 Session 中的对比,如果无法匹配则要求用户重新登录,在强模式下( strong )一旦匹配失败会删除登录者 Session,以消除攻击者重构 cookie的可能

Request Loader

有时候因为一些原因不想或者无法使用 cookie,可以将 Session 记录在其他地方,比如 Header 中或者请求参数中,那么构造用户 Session 时就需要将 user_loader替换为 request_loader,request_loader 将 request 作为参数,这样就可以从请求的任何数据中获取 Session 信息了

python flask框架下登录注册界面_Python-用户登录 Flask-Login相关推荐

  1. python做一个登录注册界面_Python 实现简单的登录注册界面

    Python 实现简单的登录注册界面 注意:编写代码之前需要导入很重要的包 import tkinter as tk import pickle from tkinter import message ...

  2. python做一个登录注册界面_python做一个登录注册界面的方法

    python做一个登录注册界面的方法 发布时间:2020-08-21 10:37:05 来源:亿速云 阅读:111 作者:小新 这篇文章主要介绍python做一个登录注册界面的方法,文中介绍的非常详细 ...

  3. 右侧按钮登录注册html,翻转式用户登录注册界面设计

    这是一款非常实用的翻转式用户登录注册界面设计效果.该用户登录注册界面使用纯CSS3来制作,在用户点击登录和注册两个按钮时,登录和注册界面可以以水平翻转的方式来回切换,效果非常的酷. 制作方法 HTML ...

  4. python flask框架下登录注册界面_Python的Flask框架中实现简单的登录功能的教程

    Python 的 Flask 框架中实现简单的登录功能的教程 , 登录是各个 web 框架中的基础功能 , 需要的朋友可以参考下 回顾 在前面的系列章节中, 我们创建了一个数据库并且学着用用户和邮件来 ...

  5. python登录注册接口_Python实现登录接口

    要求: 输入用户名和密码 认证成功,显示欢迎信息 用户名3次输入错误后,退出程序 密码3次输入错误后,锁定用户名 Readme: UserList.txt 是存放用户名和密码的文件,格式为:usern ...

  6. mysql登录注册留言_实现登录注册的留言板思路

    代码见 一.登录界面 1.  布局: a)      定width , height , margin:20px auto , box-shadow , border-radius b)      p ...

  7. python的flask实现第三方登录怎么写_Python语言的Flask框架应用程序实现使用QQ账号登录的方法...

    本文主要向大家介绍了Python语言的Flask框架应用程序实现使用QQ账号登录的方法,希望对大家学习Python语言有所帮助. Flask-OAuthlib是OAuthlib的Flask扩展实现, ...

  8. python PySide6 图书管理系统结合数据库实战教程之登录-注册界面(保姆级教程)(后续更新)

    首先默认安装了mysql8.0.29,默认安装了python. 此项目用到了python的第三方库PySide6.pymysql.pyinstaller. 目录 安装第三方库 数据库建表 py文件 注 ...

  9. python实现用户登录注册界面_实现前后端登录注册界面

    本篇博客讲解如何实现前后端的简单登录注册界面,后端代码由node.js实现,主要阐述登录注册时网页工作原理.感兴趣的同学可以参考一下. 注册界面 功能: 判断用户是否输入邮箱,密码,验证密码(前端判断 ...

最新文章

  1. 《构建之法》第6 - 7章
  2. PHP-FPM对比Swoole:Swoole多了Reactor线程监听Socket 句柄的变化 代码初始化一次不结束进程 ws tcp mqtt服务
  3. 肝!一文讲解JWT用户认证全过程
  4. 无连接网络通信程序UDP
  5. nginx修改默认端口
  6. properties文件 , properties类, 的作用
  7. python购物车结算_python购物车-基础版本
  8. python怎么提交作业_python分析作业提交情况
  9. 百度人脸识别技术应用001---百度人脸识别应用业务介绍
  10. ServletContextListener小小总结
  11. ArrayList ListItr
  12. linux是否32位系统文件夹,技术|如何判断Unix系统的一个库文件是32位还是64位的...
  13. Hive 安装配置及下载地址
  14. [Spring实战系列](2)Maven创建Spring-HelloWorld项目
  15. 智能车的转弯部分_教训:渣土车“两米生死线”千万别跨!记者带你亲身体验...
  16. 财务会计之借贷记账法的【科目方向】和【科目余额方向】分析
  17. 天仙般的王祖贤和林青霞,她们都是用AI修复的
  18. java读取tiff图像的像素值
  19. Java 获取Word中的所有插入和删除修订
  20. 好记性不如烂笔头-笔记记录方法公开

热门文章

  1. 前端:运用canvas标签绘制烟花,提前祝大家新年快乐
  2. Hi Generator
  3. 黑客利用瑞昱声卡设计缺陷监听你?
  4. JAVA斗地主案例(单列)
  5. 不用学Python的自动化办公 确定不来看看?
  6. ThinkPhp框架开发
  7. 工控机中eDP接口和LVDS接口的区别
  8. vivo X20全面屏手机推出黑金旗舰版,这个十月神秘无限
  9. WHAT DOES A SINGLE LIGHT-RAY REVEAL ABOUT A TRANSPARENT OBJECT
  10. hiredis(一个轻量级redis的c客户端)