Python Flask Web框架快速入门

Flask 入门Demo

Flask 开发环境搭建,执行如下指令:

pip install flask
# 第一节: Flask 快速入门from flask import Flask
app = Flask(__name__)@app.route('/flask')
def hello_flask():return 'Hello Flask'app.run()

核心代码剖析:

从 flask 包导入 Flask 类,通过实例化这个类,创建一个程序对象 app。

app = Flask(__name__)

注册一个处理函数,这个函数是处理某个请求的处理函数,Flask 官方把它叫做视图函数(view funciton)。使用 app.route() 装饰器来为这个函数绑定对应的 URL,当用户在浏览器访问这个 URL 的时候,就会触发这个函数,获取返回值,并把返回值显示到浏览器窗口:

@app.route('/flask')
def hello_flask():return 'Hello Flask'

最后,Flask类的run()方法在本地开发服务器上运行应用程序。

app.run(host, port, debug, options)

所有参数都是可选的

序号参数与描述
1

host

要监听的主机名。 默认为127.0.0.1(localhost)。设置为“0.0.0.0”以使服务器在外部可用

2

port

默认值为5000

3

debug

默认为false。 如果设置为true,则提供调试信息

4

options

要转发到底层的Werkzeug服务器。

Flask 基础知识

Flask 入参类型

flask 支持入参数据类型,如下所示:

转换器描述
int整型
float浮点型
path接受用作目录分隔符的斜杠
string默认,字符串
# 第二节: Flask 入参
from flask import Flask, redirectapp = Flask(__name__)# 字符串入参
@app.route('/strs/<name>')
def strs(name):return "Hello %s" % name# 浮点数入参
@app.route('/floats/<float:version>')
def floats(version):return version# 整数入参
@app.route('/ints/<int:version>')
def ints(version):return '整数为 %d' % versionapp.run(host='0.0.0.0', port=8888, debug=True)

Flask 重定向(redirect)

url_for()函数用于动态指定函数的URL地址。

# 第三节: Flask 重定向from flask import Flask, redirect, url_forapp = Flask(__name__)@app.route('/redicts')
def redicts():return redirect('https://www.baidu.com')@app.route('/admin')
def get_admin():return 'Hello Admin'@app.route('/guest/<guest>')
def get_guest(guest):return 'Hello %s as Guest' % guest@app.route('/user/<name>')
def hello_user(name):if name == 'admin':return redirect(url_for('get_admin'))else:return redirect(url_for('get_guest', guest=name))app.run()

Flask 支持到HTTP方法

默认情况下,Flask路由响应GET请求。但是,可以通过为route()装饰器提供方法参数来更改此首选项。

序号方法与描述
1

GET

以未加密的形式将数据发送到服务器。最常见的方法。

2

HEAD

和GET方法相同,但没有响应体。

3

POST

用于将HTML表单数据发送到服务器。POST方法接收的数据不由服务器缓存。

4

PUT

用上传的内容替换目标资源的所有当前表示。

5

DELETE

删除由URL给出的目标资源的所有当前表示。

# 第四节: Flask 支持HTTP方法from flask import Flaskapp = Flask(__name__)@app.route('/get_request', methods=['GET'])
def get_request():return 'GET请求'@app.route('/post_request', methods=['POST'])
def post_request():return 'POST请求'@app.route('/delete_request', methods=['DELETE'])
def delete_request():return 'DELETE请求'@app.route('/put_request', methods=['PUT'])
def put_request():return 'PUT请求'@app.route('/head_request', methods=['HEAD'])
def head_request():return 'HEAD请求'app.run()

 Flask 实战一:模拟用户登入

# Flask 模拟用户登入from flask import Flask, request, jsonifyapp = Flask(__name__)@app.route('/')
def index():return '欢迎来到主页'@app.route('/login', methods=['POST'])
def login():my_json = request.get_json()user = my_json.get('user')password = my_json.get('password')if user == 'admin' and password == '123456':# 前端和后端统一请求和返回的数据格式,返回json格式需要导入jsonify这个包# return jsonify({#     "token": "abcd123456",#     "birthday": "2024-04-18"# })return jsonify(token="abcd123456", birthdat="2024-04-18")app.run()

Flask 模板

在项目下创建 templates 文件夹,用于存放所有模板文件,并在目录下创建一个模板文件: login.html 文件

<html><body><form action = "http://localhost:5000/login" method = "post"><p>用户名:</p><p><input type = "text" name = "user" /></p><p>密码:</p><p><input type = "password" name = "password" /></p><p><input type = "submit" value = "submit" /></p></form></body>
</html>
# Flask 模拟用户登入 : 基于Templatefrom flask import Flask, request, jsonify, render_templateapp = Flask(__name__)@app.route('/')
def index():return render_template("login.html")@app.route('/login', methods=['POST'])
def login():# 由json 获取修改为表单获取user = request.form['user']password = request.form['password']if user == 'admin' and password == '123456':# 前端和后端统一请求和返回的数据格式,返回json格式需要导入jsonify这个包# return jsonify({#     "token": "abcd123456",#     "birthday": "2024-04-18"# })return jsonify(token="abcd123456", birthdat="2024-04-18")app.run()

Flask 模板文件传参

在Python代码中传入字符串,列表,字典到模板中。

from flask import Flask, render_templateapp = Flask(__name__)@app.route('/')
def index():# 字符串my_str = 'Hello Word'# int 类型my_int = 10# 数组类型my_array = [3, 4, 2, 1, 7, 9]# 字典类型my_dict = {'name': 'zhouzhiwengang','age': 31}return render_template('variable.html',my_str=my_str,my_int=my_int,my_array=my_array,my_dict=my_dict)app.run()

Flask 模板文件之静态文件

# 第六节: Flask 模板文件之静态文件
from flask import Flask, render_templateapp = Flask(__name__)@app.route("/")
def index():return render_template("static.html")app.run(debug=True)

在项目下创建 templates 文件夹,用于存放所有模板文件,并在目录下创建一个模板文件: static.html 文件

<html><head><script type = "text/javascript"src = "{{ url_for('static', filename = 'static.js') }}" ></script></head><body><input type = "button" onclick = "sayHello()" value = "Say Hello" /></body></html>

在项目下创建 static文件夹,用于存放javascript文件或支持网页显示的CSS文件,并在目录下创建一个js文件: static.js文件

function sayHello() {alert("Python 模板文件之静态资源文件")
}

Flask Request对象

Request对象的重要属性如下所列:

  • Form - 它是一个字典对象,包含表单参数及其值的键和值对。

  • args - 解析查询字符串的内容,它是问号(?)之后的URL的一部分。

  • Cookies  - 保存Cookie名称和值的字典对象。

  • files - 与上传文件有关的数据。

  • method - 当前请求方法。

# 第七节: Flask Request 对象
# Request对象的重要属性如下所列:
# Form - 它是一个字典对象,包含表单参数及其值的键和值对。
# args - 解析查询字符串的内容,它是问号(?)之后的URL的一部分。
# Cookies  - 保存Cookie名称和值的字典对象。
# files - 与上传文件有关的数据。
# method - 当前请求方法。from flask import Flask, render_template, requestapp = Flask(__name__)@app.route('/')
def student():return render_template('student.html')@app.route('/result', methods=['POST', 'GET'])
def result():if request.method == 'POST':result = request.formreturn render_template("result.html", result=result)app.run(debug=True)

在项目下创建 templates 文件夹,用于存放所有模板文件,并在目录下创建一个模板文件: student.html /result.html文件

student.html

<html><body><form action="http://localhost:5000/result" method="POST"><p>姓名 <input type = "text" name = "Name" /></p><p>物理 <input type = "text" name = "Physics" /></p><p>化学 <input type = "text" name = "chemistry" /></p><p>数学 <input type ="text" name = "Mathematics" /></p><p><input type = "submit" value = "提交" /></p></form></body>
</html>

result.html 

<html><body><table border = 1>{% for key, value in result.items() %}<tr><th> {{ key }} </th><td> {{ value }}</td></tr>{% endfor %}
</table></body>
</html>

Flask Cookie

Cookie以文本文件的形式存储在客户端的计算机上。其目的是记住和跟踪与客户使用相关的数据,以获得更好的访问者体验和网站统计信息。

Cookie 核心方法

设置cookie

默认有效期是临时cookie,浏览器关闭就失效,可以通过 max_age 设置有效期, 单位是秒

 res = make_response('set success')res.set_cookie('username', 'zhouzhiwengang', max_age=3600)

获取cookie

通过request.cookies的方式, 返回的是一个字典。

cookie = request.cookies.get('username')

删除cookie

 res = make_response('del success')res.delete_cookie('username')
# 第七节: Flask Cookie 对象
from flask import Flask, make_response, request  # 注意需导入 make_responseapp = Flask(__name__)@app.route('/set_cookie')
def set_cookie():res = make_response('set success')res.set_cookie('username', 'zhouzhiwengang', max_age=3600)return res@app.route('/get_cookie')
def get_cookie():cookie = request.cookies.get('username')return cookie@app.route('/del_cookie')
def del_cookie():res = make_response('del success')res.delete_cookie('username')return resapp.run()

Flask Session

与Cookie不同,Session(会话)数据存储在服务器上。会话是客户端登录到服务器并注销服务器的时间间隔。需要在该会话中保存的数据会存储在服务器上的临时目录中。

为每个客户端的会话分配会话ID。会话数据存储在cookie的顶部,服务器以加密方式对其进行签名。对于此加密,Flask应用程序需要一个定义的SECRET_KEY

Session对象也是一个字典对象,包含会话变量和关联值的键值对。

Session核心方法

设置密钥

app.secret_key = 'abcd12345678'

设置Session会话变量

session['username'] = request.form['username']

删除Session 会话变量

 session.pop('username', None)
# 第八节: Flask Session 对象from flask import Flask, session, redirect, url_for, escape, requestapp = Flask(__name__)app.secret_key = 'abcd12345678'@app.route('/')
def index():if 'username' in session:# session 会话获取值username = session['username']return '登录用户名是:' + username + '<br>' + \"<b><a href = '/logout'>点击这里注销</a></b>"return "您暂未登录, <br><a href = '/login'></b>" + \"点击这里登录</b></a>"@app.route('/login', methods=['GET', 'POST'])
def login():if request.method == 'POST':user = request.form['username']password = request.form['password']if user == 'admin' and password == '123456':# session 会话设值session['username'] = request.form['username']return redirect(url_for('index'))return '''<form action = "" method = "post"><p>用户名:</p><p><input type = "text" name = "username" /></p><p>密码:</p><p><input type = "password" name = "password" /></p><p><input type = "submit" value = "submit" /></p><p><input type="submit" value ="登录"/></p></form>'''@app.route('/logout')
def logout():# session 会话移除值session.pop('username', None)return redirect(url_for('index'))if __name__ == '__main__':app.run(debug=True)

Flask 错误代码

Flask类具有带有错误代码的abort()函数。

Flask.abort(code)

Code 参数采用以下值之一:

  • 400 - 用于错误请求

  • 401 - 用于未身份验证的

  • 403 - Forbidden

  • 404 - 未找到

  • 406 - 表示不接受

  • 415 - 用于不支持的媒体类型

  • 429 - 请求过多

# 第九节: Flask 错误from flask import Flask, session, redirect, url_for, escape, request, abortapp = Flask(__name__)app.secret_key = 'abcd12345678'@app.route('/')
def index():if 'username' in session:# session 会话获取值username = session['username']return '登录用户名是:' + username + '<br>' + \"<b><a href = '/logout'>点击这里注销</a></b>"return "您暂未登录, <br><a href = '/login'></b>" + \"点击这里登录</b></a>"@app.route('/login', methods=['GET', 'POST'])
def login():if request.method == 'POST':user = request.form['username']password = request.form['password']if user == 'admin' and password == '123456':# session 会话设值session['username'] = request.form['username']return redirect(url_for('index'))else:# 用户验证不通过abort(401)return '''<form action = "" method = "post"><p>用户名:</p><p><input type = "text" name = "username" /></p><p>密码:</p><p><input type = "password" name = "password" /></p><p><input type = "submit" value = "submit" /></p><p><input type="submit" value ="登录"/></p></form>'''@app.route('/logout')
def logout():# session 会话移除值session.pop('username', None)return redirect(url_for('index'))if __name__ == '__main__':app.run(debug=True)

Flask 消息反馈

Flask 模块包含 flash() 方法。它将后端处理消息传递给前端。

# 第十节: Flask 消息反馈from flask import Flask, redirect, url_for, request, render_template, flashapp = Flask(__name__)
# seesion 会话存储临时目录地址
app.secret_key = 'abcde'@app.route('/')
def index():return render_template('response.html')@app.route('/login', methods=['GET', 'POST'])
def login():error = Noneif request.method == 'POST':user = request.form['user']password = request.form['password']if user == 'admin' and password == '123456':flash('登入成功')return redirect(url_for('index'))else:# 用户验证不通过,反馈相关信息error = '非法用户名或密码,请重新登入'return render_template('login.html', error=error)if __name__ == '__main__':app.run(debug=True)

在项目下创建 templates 文件夹,用于存放所有模板文件,并在目录下创建一个模板文件: login.html /response.html文件

login.html

<html><body><form action = "http://localhost:5000/login" method = "post"><p>用户名:</p><p><input type = "text" name = "user" /></p><p>密码:</p><p><input type = "password" name = "password" /></p><p><input type = "submit" value = "submit" /></p></form>{% if error %}<p><strong>错误信息</strong>: {{ error }}</p>{% endif %}</body>
</html>

response.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Flask 消息反馈</title>
</head>
<body>{% with messages = get_flashed_messages() %}{% if messages %}{% for message in messages %}<p>{{ message }}</p>{% endfor %}{% endif %}{% endwith %}
<h3>Welcome!</h3>
<a href = "{{ url_for('login') }}">登入</a>
</body>
</html>

Flask 文件上传

在 Flask 中处理文件上传非常简单。它需要一个 HTML 表单,其 ​enctype​ 属性设置为“​multipart/form-data​,将文件发布到 URL。

URL 处理程序从 ​request.files[] 对象中提取文件,并将其保存到所需的位置。

每个上传的文件首先会保存在服务器上的临时位置,然后将其实际保存到它的最终位置。

目标文件的名称可以是硬编码的,也可以从request.files[file] ​对象的​ filename ​属性中获取。但是,建议使用secure_filename()​ 函数获取它的安全版本。

可以在 Flask 对象的配置设置中定义默认上传文件夹的路径和上传文件的最大大小。

app.config['UPLOAD_FOLDER'] 定义上传文件夹的路径 app.config['MAX_CONTENT_LENGTH'] 指定要上传的文件的最大大小(以字节为单位)
# 第十一节: Flask 文件上传from flask import Flask, render_template, request
from werkzeug.utils import secure_filenameimport osapp = Flask(__name__)
UPLOAD_FOLDER = 'upload'
if not os.path.exists(UPLOAD_FOLDER):os.makedirs(UPLOAD_FOLDER)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER@app.route('/upload')
def upload_file():return render_template('upload.html')@app.route('/uploader', methods=['GET', 'POST'])
def uploader():if request.method == 'POST':f = request.files['file']print(request.files)f.save(os.path.join(app.config['UPLOAD_FOLDER'], secure_filename(f.filename)))return '文件上传成功'else:return render_template('upload.html')if __name__ == '__main__':app.run(debug=True)

Flask 拓展

Flask常用扩展包:

Flask-SQLalchemy:操作数据库;

Flask-script:插入脚本;

Flask-migrate:管理迁移数据库;

Flask-Session:Session存储方式指定;

Flask-WTF:表单;

Flask-Mail:邮件;

Flask-Bable:提供国际化和本地化支持,翻译;

Flask-Login:认证用户状态;

Flask-OpenID:认证;

Flask-RESTful:开发REST API的工具;

Flask-Bootstrap:集成前端Twitter Bootstrap框架;

Flask-Moment:本地化日期和时间;

Flask-Admin:简单而可扩展的管理接口的框架

Flask 拓展之Flask-SQLalchemy

SQLAlchemy是一个关系型数据库框架,它提供了高层的ORM和底层的原生数据库的操作。flask-sqlalchemy是一个简化了SQLAlchemy操作的flask扩展。

安装flask-sqlalchemy扩展, 执行如下指令:
pip install -U Flask-SQLAlchemypip install flask-mysqldbpip install pymysql
SQLAlchemy支持字段类型
类型名python中类型说明
Integerint普通整数,一般是32位
SmallIntegerint取值范围小的整数,一般是16位
BigIntegerint或long不限制精度的整数
Floatfloat浮点数
Numericdecimal.Decimal普通整数,一般是32位
Stringstr变长字符串
Textstr变长字符串,对较长或不限长度的字符串做了优化
Unicodeunicode变长Unicode字符串
UnicodeTextunicode变长Unicode字符串,对较长或不限长度的字符串做了优化
Booleanbool布尔值
Datedatetime.date时间
Timedatetime.datetime日期和时间
LargeBinarystr二进制文件
SQLAlchemy列选项
选项名说明
primary_key如果为True,代表表的主键
unique如果为True,代表这列不允许出现重复的值
index如果为True,为这列创建索引,提高查询效率
nullable如果为True,允许有空值,如果为False,不允许有空值
default为这列定义默认值
SQLAlchemy关系选项
选项名说明
backref在关系的另一模型中添加反向引用
primary join明确指定两个模型之间使用的联结条件
uselist如果为False,不使用列表,而使用标量值
order_by指定关系中记录的排序方式
secondary指定多对多中记录的排序方式
secondary join在SQLAlchemy中无法自行决定时,指定多对多关系中的二级联结条件
Flask-SQLalchemy 实战之快速入门
# 第十一节: Flask 拓展之数据库(flask-sqlalchemy), 快速入门
# 导入Flask及相关扩展库
from flask import Flask
from flask_sqlalchemy import SQLAlchemy# 创建Flask应用实例
app = Flask(__name__)# 配置MySQL数据库连接
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:123456@192.168.43.10/house'
db = SQLAlchemy(app)# 定义ORM模型,表示数据库表
class Table(db.Model):__tablename__ = 'base_house'id = db.Column(db.String(255), primary_key=True)# 路由函数,查询库下所有表名,并返回
@app.route('/')
def get_tables():tables = Table.query.all()house_list = []for user in tables:user_data = {'id': user.id}house_list.append(user_data)return {'users': house_list}if __name__ == '__main__':app.run()
Flask-SQLalchemy 实战之分页查询和参数筛选
# 第十一节: Flask 拓展之数据库(flask-sqlalchemy), 分页 + 入参查询
# 导入Flask及相关扩展库
from flask import Flask, request, jsonify
from flask_sqlalchemy import SQLAlchemy# 创建Flask应用实例
app = Flask(__name__)# 配置MySQL数据库连接
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:123456@192.168.43.10/house'
db = SQLAlchemy(app)# 定义ORM模型,表示数据库表
class Table(db.Model):__tablename__ = 'base_house'id = db.Column(db.String(255), primary_key=True)project_no = db.Column(db.String(255))project_name = db.Column(db.String(255))project_address = db.Column(db.String(255))# 路由函数,查询库下所有表名,并返回
@app.route('/', methods=['POST'])
def get_tables():parame_json = request.get_json()page = parame_json.get('page')size = parame_json.get('size')name = parame_json.get('name')if name:houses = Table.query.filter_by(project_name=name).paginate(page=page, per_page=size, error_out=False)else:houses = Table.query.paginate(page=page, per_page=size, error_out=False)house_list = []for house in houses:house_data = {'id': house.id,'projectNo': house.project_no,'projectName': house.project_name,'projectAddress': house.project_address}house_list.append(house_data)return jsonify({'users': house_list,'total_pages': houses.pages,'current_page': houses.page})if __name__ == '__main__':app.run()

涉及base_house 表DDL:

CREATE TABLE `base_house` (`id` varchar(64) NOT NULL,`project_no` varchar(128) DEFAULT NULL,`project_name` varchar(256) DEFAULT NULL,`project_address` varchar(256) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Flask 拓展之Flask-Login

扩展 Flask-Login 提供了实现用户认证需要的各类功能函数,我们将使用它来实现程序的用户认证,首先来安装它:

pip install flask-login

app.py:初始化 Flask-Login

from flask_login import LoginManagerlogin_manager = LoginManager(app)  # 实例化扩展类@login_manager.user_loader
def load_user(user_id):  # 创建用户加载回调函数,接受用户 ID 作为参数user = User.query.get(int(user_id))  # 用 ID 作为 User 模型的主键查询对应的用户return user  # 返回用户对象

Table模型类继承 Flask-Login 提供的 UserMixin 类:

# 定义ORM模型,表示数据库表
class Table(UserMixin, db.Model):__tablename__ = 't_admin'id = db.Column(db.Integer, primary_key=True)username = db.Column(db.String(30))userpwd = db.Column(db.String(100))

 

# 第十二节: Flask 拓展之数据库(flask-sqlalchemy)/认证框架(flask-login), 使用用户登入并方法鉴权
from flask import Flask, request, jsonify, redirect, url_for, render_template
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user# 创建Flask应用实例
app = Flask(__name__)
# seesion 会话存储临时目录地址
app.secret_key = 'abcde1234'# 配置MySQL数据库连接
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:123456@192.168.43.10/house'
db = SQLAlchemy(app)# 初始化登录管理器
login_manager = LoginManager()
login_manager.init_app(app)# 定义ORM模型,表示数据库表
class Table(UserMixin, db.Model):__tablename__ = 't_admin'id = db.Column(db.Integer, primary_key=True)username = db.Column(db.String(30))userpwd = db.Column(db.String(100))# 加载用户的回调函数
@login_manager.user_loader
def load_user(user_id):return Table.query.get(int(user_id))# 定义登录路由
@app.route('/login', methods=['GET', 'POST'])
def login():if request.method == 'POST':username = request.form['username']password = request.form['password']user = Table.query.filter_by(username=username).first()if user and user.userpwd == password:login_user(user)return redirect(url_for('dashboard'))return render_template('auth_login.html')# 定义需要鉴权的页面
@app.route('/dashboard')
@login_required
def dashboard():return render_template('dashboard.html')# 定义登出路由
@app.route('/logout')
@login_required
def logout():logout_user()return redirect(url_for('login'))if __name__ == '__main__':app.run()

Flask 拓展之Flask-JWT-Extended

JWT简介

具体原理请参考:JSON Web Token 入门教程

JWT结构

JWT由三部分组成:

  • 头部(Header):通常包含令牌的类型(JWT)和使用的加密算法。
  • 载荷(Payload):包含有关用户或其他数据的信息。例如,用户ID、角色或其他自定义数据。
  • 签名(Signature):由头部、载荷和密钥组合而成的签名,用于验证令牌的完整性和来源可信度。

JWT生成和校验

  1. 用户登录时,服务器使用密钥签署JWT,并将其返回给客户端。
  2. 客户端在以后的请求中发送JWT作为身份验证令牌。
  3. 服务器验证JWT的签名以确保其完整性,然后使用载荷中的信息进行用户身份验证和授权。

Flask-JWT-Extended 

Flask-JWT-Extended是一个Python库,用于在 Flask 应用程序中添加JSON Web令牌(JWT)支持。它是一个插件,可以通过安装它来扩展Flask应用程序的功能。

官网地址:Flask-JWT_Extended 官网

Flask-JWT-Extended 安装

pip install Flask-JWT-Extended

实战:Flask-SQLalchemy + MySQL 8  + Flask-JWT-Extended 实现前后端分离用户认证和鉴权。

# _*_ coding : UTF-8_*_
# 开发者 : zhuozhiwengang
# 开发时间 : 2024/4/19 9:26
# 文件名称 : 19
# 开发工具 : PyCharm
# 第十二节: Flask 拓展之数据库(flask-sqlalchemy)/认证框架(flask-jwt-extend), 实现用户前后端分离认证和鉴权
from flask import Flask, request, jsonify, redirect, url_for, render_template, abort
from flask_sqlalchemy import SQLAlchemy
from flask_jwt_extended import (JWTManager, jwt_required, create_access_token, get_jwt_identity)# 创建Flask应用实例
app = Flask(__name__)
# 用于签名JWT的密钥
app.config['JWT_SECRET_KEY'] = 'abc123'# 配置MySQL数据库连接
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:123456@192.168.43.10/house'
db = SQLAlchemy(app)# 初始化JWT扩展
jwt = JWTManager(app)# 定义ORM模型,表示数据库表
class Table(db.Model):__tablename__ = 't_admin'id = db.Column(db.Integer, primary_key=True)username = db.Column(db.String(30))userpwd = db.Column(db.String(100))# 定义登录路由
@app.route('/login', methods=['GET', 'POST'])
def login():if request.method == 'POST':username = request.form['username']password = request.form['password']user = Table.query.filter_by(username=username).first()if user and user.userpwd == password:access_token = create_access_token(identity=username)return jsonify(access_token=access_token)else:# 用户名或密码错误abort(401)# 定义需要鉴权的页面
@app.route('/dashboard')
@jwt_required()  # 这个装饰器要求请求必须携带有效的JWT令牌
def dashboard():# 使用get_jwt_identity访问当前用户的身份current_user = get_jwt_identity()return jsonify(logged_in_as=current_user)if __name__ == '__main__':app.run()

第一种情况:输入错误用户名或密码,提示401错误代码

控制台输出信息:

WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.* Running on http://127.0.0.1:5000
Press CTRL+C to quit
127.0.0.1 - - [19/Apr/2024 09:36:45] "POST /login HTTP/1.1" 401 -

 第二种情况:输入正确用户名和密码,获取凭证Token

 第三种情况:拼接头信息,访问受保护资源

Flask-JWT-Extended 核心代码讲解 

初始化

from flask import Flask
from flask_jwt_extended import (JWTManager, jwt_required, create_access_token, get_jwt_identity)app = Flask(__name__)
# 用于签名JWT的密钥
app.config['JWT_SECRET_KEY'] = 'your-secret-key' # 初始化JWT扩展
jwt = JWTManager(app)

生成和校验

  • 定义了 /login 路由,用于用户登录并获取JWT令牌。在这个路由中,首先从请求中获取用户名和密码(这里是 “zzg” 和 “123456”)。如果匹配成功,就使用 create_access_token 函数生成JWT令牌,并返回给客户端。
  • 定义了 /protected 路由,它是受保护的路由,只有在请求中包含有效的JWT令牌时才能访问。这是通过 @jwt_required() 装饰器实现的。
    • 如果请求中没有有效的JWT令牌,访问该路由会返回未授权的响应。
    • 如果令牌有效,路由会使用 get_jwt_identity() 函数获取JWT中的身份信息(在示例中为用户名)然后返回一个JSON响应,显示已登录的用户

 Flask-JWT-Extended 优化:设置Token有效期、刷新Token

设置Token有效期

设置JWT的过期时间是一种重要的安全措施,可以帮助确保令牌不会无限期有效,提高了应用程序的安全性。

方法一:

使用 app.config['JWT_ACCESS_TOKEN_EXPIRES'] 来设置JWT的访问token默认过期时间为1小时。

# 设置ACCESS_TOKEN的默认过期时间为1小时
app.config['JWT_ACCESS_TOKEN_EXPIRES'] = timedelta(hours=1)

方法二:

当使用create_access_token函数创建JWT令牌时,也可以通过传递expires_delta参数来覆盖默认的过期时间,例如:

  • 这将覆盖默认的过期时间,使得令牌在30分钟后过期。
from datetime import timedelta
# 设置ACCESS_TOKEN的默认过期时间为30分钟
access_token = create_access_token(identity=username, expires_delta=timedelta(minutes=30))

刷新Token 

认证Token与刷新Token差异

访问tokenAccess Token刷新tokenRefresh Token
用途用于访问受保护的资源用于获取新的访问token
生命周期默认为15分钟默认为30天
显式指定生命周期JWT_ACCESS_TOKEN_EXPIRESJWT_REFRESH_TOKEN_EXPIRES
储存方式在请求的头信息(Header)中的 “Authorization” 字段中一般存储在服务器端的数据库

每个用户生成的刷新token访问token是一一对应的,

当用户登录成功后,服务器会为该用户生成一对刷新token访问token,并将它们关联到用户的身份(通常是用户的用户名或ID)。这样,每个用户都有自己唯一的刷新token访问token

刷新token用于获取新的访问token,以延长用户的会话时间。只有拥有有效的刷新token的用户才能获取新的访问token,而访问token则用于实际访问受保护的资源。

实战:Flask-SQLalchemy + MySQL 8  + Flask-JWT-Extended 实现前后端分离用户认证和鉴权。添加刷新Token和使用刷新Token鉴权。

# 第十二节: Flask 拓展之数据库(flask-sqlalchemy)/认证框架(flask-jwt-extend), 实现用户前后端分离认证和鉴权
from flask import Flask, request, jsonify, redirect, url_for, render_template, abort
from flask_sqlalchemy import SQLAlchemy
from flask_jwt_extended import (JWTManager, jwt_required, create_access_token, get_jwt_identity, create_refresh_token)# 创建Flask应用实例
app = Flask(__name__)
# 用于签名JWT的密钥
app.config['JWT_SECRET_KEY'] = 'abc123'# 配置MySQL数据库连接
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:123456@192.168.43.10/house'
db = SQLAlchemy(app)# 初始化JWT扩展
jwt = JWTManager(app)# 定义ORM模型,表示数据库表
class Table(db.Model):__tablename__ = 't_admin'id = db.Column(db.Integer, primary_key=True)username = db.Column(db.String(30))userpwd = db.Column(db.String(100))# 定义登录路由
@app.route('/login', methods=['GET', 'POST'])
def login():if request.method == 'POST':username = request.form['username']password = request.form['password']user = Table.query.filter_by(username=username).first()if user and user.userpwd == password:access_token = create_access_token(identity=username)refresh_token = create_refresh_token(identity=username)return jsonify(access_token=access_token, refresh_token=refresh_token)else:# 用户名或密码错误abort(401)# 使用刷新token获取新的访问token
@app.route("/refresh", methods=["POST"])
@jwt_required(refresh=True)  # 使用刷新token进行验证
def refresh():current_user = get_jwt_identity()access_token = create_access_token(identity=current_user)return jsonify(access_token=access_token)# 定义需要鉴权的页面
@app.route('/dashboard')
@jwt_required()  # 这个装饰器要求请求必须携带有效的JWT令牌
def dashboard():# 使用get_jwt_identity访问当前用户的身份current_user = get_jwt_identity()return jsonify(logged_in_as=current_user)if __name__ == '__main__':app.run()

相关截图:

Flask 拓展之flask_restful 

flask_restful安装

pip install flask_restful

实战:Flask-SQLalchemy + MySQL 8 +Flask_Restful 实现Restful 接口

from flask import Flask, request, jsonify
from flask_restful import Api, Resource
from flask_sqlalchemy import SQLAlchemy# 创建Flask应用实例
app = Flask(__name__)# 配置MySQL数据库连接
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:123456@192.168.43.10/house'
db = SQLAlchemy(app)
api = Api(app)# 定义ORM模型,表示数据库表
class Table(db.Model):__tablename__ = 'base_house'id = db.Column(db.String(255), primary_key=True)project_no = db.Column(db.String(255))project_name = db.Column(db.String(255))project_address = db.Column(db.String(255))class UserAPI(Resource):def get(self, user_id):user = Table.query.get(user_id)if user:return {'id': user.id, 'projectNo': user.project_no, 'projectName': user.project_name, 'projectAddress': user.project_address}else:return {'message': 'House not found'}, 404def post(self):data = request.get_json()new_user = Table(project_no=data['projectNo'], project_name=data['projectName'], project_address=data['projectAddress'], id=data['id'])db.session.add(new_user)db.session.commit()return {'message': '创建成功'}, 201def delete(self, user_id):user = Table.query.get(user_id)if user:db.session.delete(user)db.session.commit()return {'message': '删除成功'}else:return {'message': '记录未找到'}, 404api.add_resource(UserAPI, '/user', '/user/<user_id>')if __name__ == '__main__':app.run(port=8081)

Flask 高级

待补充Flask高级内容主要涉及:Python 多线程、Python连接Redis、Python连接MongoDB、Python 连接Elasticsearch、Python MinoIO 文件服务器。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/314061.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

五种主流数据库:集合运算

关系型数据库中的表与集合理论中的集合类似&#xff0c;表是由行&#xff08;记录&#xff09;组成的集合。因此&#xff0c;SQL 支持基于数据行的各种集合运算&#xff0c;包括并集运算&#xff08;Union&#xff09;、交集运算&#xff08;Intersect&#xff09;和差集运算&a…

springcloud Ribbon的详解

1、Ribbon是什么 Ribbon是Netflix发布的开源项目&#xff0c;Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的框架。 2、Ribbon能干什么 LB负载均衡(Load Balance)是什么&#xff1f;简单的说就是将用户的请求平摊的分配到多个服务上&#xff0c;从而达…

C++:const成员和取地址操作符

目录 一、const成员 二、取地址及const取地址操作符重载 一、const成员 将const修饰的“成员函数”称之为const成员函数&#xff0c;const修饰类成员函数&#xff0c;实际修饰该成员函数 隐含的this指针&#xff0c;表明在该成员函数中不能对类的任何成员进行修改。 注&…

ESLlint重大更新后,使用旧版ESLint搭配Prettier的配置方式

概要 就在前几天&#xff0c;ESLint迎来了一次重大更新&#xff0c;9.0.0版本&#xff0c;根据官方文档介绍&#xff0c;使用新版的先决条件是Node.js版本必须是18.18.0、20.9.0&#xff0c;或者是>21.1.0的版本&#xff0c;新版ESLint将不再直接支持以下旧版配置(非扁平化…

【CSS】使用 scroll snap 实现页面的垂直大屏滚动

CSS 属性 scroll-snap-type 设置了在有滚动容器的情形下吸附至吸附点的严格程度。 scroll-snap-type 使用 scroll snap 也可以用于垂直滚动&#xff0c;全屏展示就是一个很好的例子: <main><section class"section section-1"></section><sect…

pytest使用 pytest-rerunfailures 插件实现失败用例重跑功能

使用 pytest 进行测试时&#xff0c;你可以通过安装并配置 pytest-rerunfailures 插件来实现失败用例重跑功能。以下是一个示例说明&#xff1a; 假设你有一个测试文件 test_example.py 包含如下测试用例&#xff1a; import pytestpytest.mark.parametrize("num",…

Idea:通义千问插件

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 一、通义千问大模型 二、程序编写助手 三、Idea安装通义千问插件 总结 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、通义千问大模型…

python 中使用 ESP8266 实现语音识别(或热词检测)

介绍 我的大部分家庭自动化都是通过对网络中的设备执行 HTTP 请求来控制的。 (例如:开灯、打开收音机、控制加热系统...... 这可以使用ESP8266轻松完成。我有一个控制器和一个触摸传感器,当我在床上时用它来控制灯光和音乐。 像 Amazon Echo 或 Google Homepod 一样添加语…

基于harris角点和RANSAC算法的图像拼接matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 MATLAB2022a 3.部分核心程序 ....................................................................... I1_harris fu…

某翻译平台翻译接口逆向之webpack学习

逆向网址 aHR0cHM6Ly9mYW55aS55b3VkYW8uY29tLw 逆向链接 aHR0cHM6Ly9mYW55aS55b3VkYW8uY29tLyMv 逆向接口 aHR0cHM6Ly9kaWN0LnlvdWRhby5jb20vd2VidHJhbnNsYXRl 逆向过程 请求方式 POST 逆向参数 sign c168e4cb76169e90f82d28118dbd24d2 接口请求结果解密 过程分析 根据XHR…

计算机网络—— book

文章目录 一、概述1.1互联网的核心部分1&#xff0e;电路交换的主要特点2&#xff0e;分组交换的主要特点 1.2.计算机网络的性能1&#xff0e;速率2&#xff0e;带宽3&#xff0e;吞吐量4&#xff0e;时延5&#xff0e;利用率 1.3.计算机网络体系结构协议与划分层次具有五层协议…

用爬虫玩转石墨文档

目录 前言 一、什么是爬虫 二、爬虫原理 三、使用Python实现爬虫 1.安装Python库 2.爬取石墨文档内容 3.解析HTML内容 四、实际应用案例 1.批量下载附件 2.统计文档字数 3.自动化更新文档 总结 前言 在当今信息化时代&#xff0c;文档协作平台早已成为我们日常工作…

H5点击复制功能 兼容安卓、IOS

效果图 HTML代码 <div>链接&#xff1a;<span style"color: #FF8A21" click"CopyUrl" id"copyId"> https://blog.csdn.net/qq_51463650?spm1000.2115.3001.5343</span> </div>复制方法 const CopyUrl () > {let …

QT跨平台读写Excel

QT跨平台读写Excel 背景Excel工具CMakeLists.txt工程目录 背景 开发框架QT&#xff0c;makefile构建工具CMake&#xff0c;编译器MinGW Excel工具 考虑跨平台则不能使用针对微软COM组件的QAxObject来读写Excel&#xff0c;因此使用开源QtXlsx。 这里是将QXlsx当做源码嵌入使…

如何快速学习盲打键盘的指法

学习盲打键盘的指法需要一定的时间和练习&#xff0c;但是以下几个方法可以帮助你加快学习的速度&#xff1a; 掌握正确的手位&#xff1a;了解标准的键盘布局以及手指应该放置的位置是学习盲打的第一步。在QWERTY键盘上&#xff0c;你的左手应该放在ASDF键上&#xff0c;右手应…

Git--基础学习--面向企业--持续更新

一、基础学习 1.1基本命令 //查询基础信息 git config --global --list //选取合适位置创建 mkdir 文件名 //创建文件夹 //全局配置 git config --global user.email "****e***i" git config --global user.name "*** K****"//--------------------进入…

10.Godot Input与自定义单例的使用

单例 单例是一个可以在任何一个脚本中对其进行直接访问的对象&#xff0c;分为内置单例与自定义单例。每个单例都是独一无二的对象。内置单例不是节点&#xff0c;主要成员是各类 Server&#xff0c;开发者可以使用它们直接控制游戏程序的图形与音效等内容。此外&#xff0c;还…

Lock-It for Mac(应用程序加密工具)

OSXBytes Lock-It for Mac是一款功能强大的应用程序加密工具&#xff0c;专为Mac用户设计。该软件具有多种功能&#xff0c;旨在保护用户的隐私和数据安全。 Lock-It for Mac v1.3.0激活版下载 首先&#xff0c;Lock-It for Mac能够完全隐藏应用程序&#xff0c;使其不易被他人…

CYCLE:学习自我完善代码生成

目录 IntriductionOverview of the Approach 预训练的代码语言模型在代码生成方面取得了可喜的性能&#xff0c;并提高了人类开发人员的编程效率。然而&#xff0c;现有的代码 LM 评估通常忽略了它们的 自我求精能力&#xff0c;这些评估仅关注一次性预测的准确性。对于代码 L…

手拉手安装Kafka2.13发送和消费消息

Kafka是一种高吞吐量的分布式发布订阅消息系统&#xff0c;它可以处理消费者在网站中的所有动作流数据。 Kafka启动方式有Zookeeper和Kraft&#xff0c;两种方式只能选择其中一种启动&#xff0c;不能同时使用。 Kafka下载https://downloads.apache.org/kafka/3.7.0/kafka_2.…