前端Python应用指南(六)构建RESTful API:使用Flask和Django实现用户认证与授权
《写给前端的python应用指南》系列:
- (一)快速构建 Web 服务器 - Flask vs Node.js 对比
- (二)深入Flask:理解Flask的应用结构与模块化设计
- (三)Django vs Flask:哪种框架适合构建你的下一个Web应用?
- (四)Django实战:创建一个简单的博客系统
- (五)用FastAPI快速构建高性能API
在构建现代Web应用时,用户认证与授权是非常重要的部分。无论是通过用户名和密码登录,还是通过OAuth2、JWT等方式进行身份验证,确保只有授权的用户可以访问敏感数据是每个API设计的核心。本篇博文将详细介绍如何使用Flask和Django构建RESTful API,并实现用户认证与授权功能,包括JWT(JSON Web Tokens)的使用。
一、概述
RESTful API通常用于前后端分离的应用,用户认证与授权机制用于保护API,使得只有经过认证的用户才能访问特定的资源。JWT(JSON Web Token)作为一种轻量级的认证方式,广泛应用于前后端分离的Web应用中。
在本文中,我们将分别使用Flask和Django实现:
- 用户注册
- 用户登录(并生成JWT)
- 保护需要授权的API(通过JWT)
二、Flask实现用户认证与授权
Flask是一个轻量级Web框架,非常适合用来快速构建RESTful API。我们将通过Flask和Flask-JWT-Extended扩展来实现JWT认证。
2.1 安装依赖
首先,我们需要安装Flask和Flask-JWT-Extended。
pip install flask flask-jwt-extended flask-sqlalchemy
2.2 创建Flask应用
我们将创建一个简单的Flask应用,包含用户注册、登录和JWT认证的功能。
- 初始化Flask应用:
from flask import Flask, request, jsonify
from flask_sqlalchemy import SQLAlchemy
from flask_jwt_extended import JWTManager, create_access_token, jwt_required, get_jwt_identityapp = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///users.db' # 使用SQLite数据库
app.config['JWT_SECRET_KEY'] = 'your_jwt_secret_key' # JWT的密钥db = SQLAlchemy(app)
jwt = JWTManager(app)
- 创建用户模型:
我们将创建一个用户模型,用户将具有username
和password
字段。
class User(db.Model):id = db.Column(db.Integer, primary_key=True)username = db.Column(db.String(80), unique=True, nullable=False)password = db.Column(db.String(120), nullable=False)def __repr__(self):return f'<User {self.username}>'
- 用户注册:
用户注册时,我们将验证输入,并将密码进行哈希处理后存入数据库。
from werkzeug.security import generate_password_hash@app.route('/register', methods=['POST'])
def register():data = request.get_json()username = data.get('username')password = data.get('password')# 检查用户是否已存在if User.query.filter_by(username=username).first():return jsonify({"msg": "User already exists"}), 400# 哈希处理密码hashed_password = generate_password_hash(password, method='sha256')new_user = User(username=username, password=hashed_password)db.session.add(new_user)db.session.commit()return jsonify({"msg": "User created successfully"}), 201
- 用户登录并生成JWT:
用户登录时,我们验证用户名和密码是否匹配,若匹配则返回一个JWT。
from werkzeug.security import check_password_hash@app.route('/login', methods=['POST'])
def login():data = request.get_json()username = data.get('username')password = data.get('password')user = User.query.filter_by(username=username).first()if user and check_password_hash(user.password, password):access_token = create_access_token(identity=username)return jsonify(access_token=access_token), 200else:return jsonify({"msg": "Invalid credentials"}), 401
- 受保护的API:
我们使用@jwt_required()
装饰器来保护需要授权的API。用户必须在请求头中提供有效的JWT才能访问这些API。
@app.route('/protected', methods=['GET'])
@jwt_required()
def protected():current_user = get_jwt_identity() # 获取当前用户的身份信息return jsonify(logged_in_as=current_user), 200
- 运行Flask应用:
if __name__ == '__main__':db.create_all() # 创建数据库表app.run(debug=True)
2.3 测试Flask API
你可以使用Postman或者curl
工具来测试这些API接口:
-
注册用户:
POST /register
- 请求体:
{"username": "john", "password": "password123"}
- 响应:
{"msg": "User created successfully"}
- 请求体:
-
用户登录:
POST /login
- 请求体:
{"username": "john", "password": "password123"}
- 响应:
{"access_token": "jwt_token_here"}
- 请求体:
-
访问受保护的API:
GET /protected
- 请求头:
Authorization: Bearer <jwt_token_here>
- 响应:
{"logged_in_as": "john"}
- 请求头:
三、Django实现用户认证与授权
Django是一个功能强大的Web框架,适用于构建复杂的Web应用。在Django中实现JWT认证,我们通常会使用djangorestframework
和djangorestframework-simplejwt
这两个库来进行集成。
3.1 安装依赖
首先,我们需要安装Django、Django REST framework以及JWT相关库。
pip install django djangorestframework djangorestframework-simplejwt
3.2 创建Django项目和应用
django-admin startproject myproject
cd myproject
python manage.py startapp accounts
3.3 配置Django项目
在myproject/settings.py
中,添加rest_framework
和accounts
到INSTALLED_APPS
:
INSTALLED_APPS = [...'rest_framework','accounts',
]
然后,配置JWT设置:
REST_FRAMEWORK = {'DEFAULT_AUTHENTICATION_CLASSES': ['rest_framework_simplejwt.authentication.JWTAuthentication',],
}
3.4 创建用户模型和序列化器
我们将在accounts/models.py
中创建用户模型,并在accounts/serializers.py
中创建序列化器。
- 创建用户模型:
在accounts/models.py
文件中,我们可以使用Django的默认用户模型或者自定义一个用户模型:
from django.contrib.auth.models import AbstractUserclass User(AbstractUser):pass
- 创建序列化器:
在accounts/serializers.py
文件中,我们为用户注册和登录创建序列化器:
from rest_framework import serializers
from django.contrib.auth.models import Userclass UserSerializer(serializers.ModelSerializer):class Meta:model = Userfields = ['username', 'password']def create(self, validated_data):user = User.objects.create_user(**validated_data)return user
3.5 创建视图和URL路由
在accounts/views.py
中,我们使用APIView
来处理注册、登录以及JWT认证。
- 用户注册视图:
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .serializers import UserSerializerclass RegisterView(APIView):def post(self, request):serializer = UserSerializer(data=request.data)if serializer.is_valid():serializer.save()return Response({"msg": "User created successfully"}, status=status.HTTP_201_CREATED)return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
- 用户登录视图(获取JWT):
from rest_framework_simplejwt.tokens import RefreshTokenclass LoginView(APIView):def post(self, request):username = request.data.get("username")password = request.data.get("password")user = authenticate(username=username, password=password)if user:refresh = RefreshToken.for_user(user)access_token = str(refresh.access_token)return Response({"access_token": access_token}, status=status.HTTP_200_OK)return Response({"msg": "Invalid credentials"}, status=status.HTTP_401_UNAUTHORIZED)
- 受保护的视图:
from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIViewclass ProtectedView(APIView):permission_classes = [IsAuthenticated]def get(self, request):return Response({"msg": "You have access to this protected view."}, status=status.HTTP_200_OK)
3.6 配置URL路由
在accounts/urls.py
中,配置相应的路由:
from django.urls import path
from .views import RegisterView, LoginView, ProtectedViewurlpatterns = [path('register/', RegisterView.as_view(), name='register'),path('login/', LoginView.as_view(), name='login'),path('protected/', ProtectedView.as_view(), name='protected'),
]
在myproject/urls.py
中,包含accounts/urls.py
:
from django.contrib import admin
from django.urls import path, includeurlpatterns = [path('admin/', admin.site.urls),path('api/accounts/', include('accounts.urls')),
]
3.7 运行Django项目
python manage.py runserver
3.8 测试Django API
使用Postman或curl
测试以下API:
- 注册用户:
POST /api/accounts/register/
- 用户登录:
POST /api/accounts/login/
- 访问受保护的API:
GET /api/accounts/protected/
(需要JWT令牌)
四、总结
通过本文的示例,我们分别展示了如何使用Flask和Django实现用户认证与授权,保护RESTful API。两种框架都支持JWT认证,但在实现上有所不同:
- Flask适合轻量级项目,灵活且简洁。
- Django则更适合复杂的应用,具有更强的功能和更好的扩展性。
无论你选择Flask还是Django,它们都能提供高效、安全的认证方式,并能帮助你快速构建可扩展的RESTful API。希望本文的示例能帮助你在实际项目中更好地实现用户认证与授权功能!
相关文章:

前端Python应用指南(六)构建RESTful API:使用Flask和Django实现用户认证与授权
《写给前端的python应用指南》系列: (一)快速构建 Web 服务器 - Flask vs Node.js 对比(二)深入Flask:理解Flask的应用结构与模块化设计(三)Django vs Flask:哪种框架适…...

【Unity3D】基于UGUI——简易版 UI框架
https://github.com/AMikeW/BStandShaderResources/blob/master/milk_UIFramework.unitypackage UI框架支持如下功能: 1、层级控制 2、支持面板多次打开时,隐藏前一个打开的面板,当关闭面板时,能够恢复前一个打开面板状态 3、支…...

算法排序算法
文章目录 快速排序[leetcode 215数组中的第K个最大元素](https://leetcode.cn/problems/kth-largest-element-in-an-array/)分析题解快速排序 桶排序[leetcode 347 前K个高频元素](https://leetcode.cn/problems/top-k-frequent-elements/)分析题解 快速排序 leetcode 215数组…...

第3章 总线
总线的定义 为多个部件 分时共享 公共信息传送线路。 系统之间、模块之间、芯片内部用来传递信息信号线集合。 共享 总线上可连接多个部件 各部件间相互交换信息 都可通过总线来。 分时 同一时刻 总线上只能传 一个部件信息。 采用标准总线的优点 简化系统软硬件设计 从硬件角度…...

手机实时提取SIM卡打电话的信令声音-双卡手机来电如何获取哪一个卡的来电
手机实时提取SIM卡打电话的信令声音 --双卡手机来电如何获取哪一个卡的来电 一、前言 前面的篇章《手机实时提取SIM卡打电话的信令声音-智能拨号器的双SIM卡切换方案》中,我们论述了局域网SIP坐席通过手机外呼出去时,手机中主副卡的呼叫调度策略。 但…...

共阳极LED的控制与短路问题解析
共阳极LED的控制与短路问题解析 在电子电路中,LED(发光二极管)是最常见的元件之一。LED的连接方式分为共阳极和共阴极,不同的连接方式决定了LED的控制逻辑。本文将重点讲解共阳极LED的工作原理,并解答“为什么给1不会…...

华为消费级QLC SSD来了
近日,有关消息显示,华为的消费级SSD产品线,eKitStor Xtreme 200E系列,在韩国一家在线零售商处首次公开销售,引起了业界的广泛关注。 尽管华为已经涉足服务器级别的SSD制造多年,但直到今年6月才正式推出面向…...

liunx下载gitlab
1.地址: https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/ 安装 postfix 并启动 yum install postfix systemctl start postfix systemctl enable postfix ssh服务启动 systemctl enable sshd systemctl start sshd开放 ssh 以及 http 服务,…...

深度学习模型预测值集中在某一个值
深度学习模型,训练过程中,经常遇到预测的结果集中在某个值,而且在学习的过程中会变,样例如下。 主要有如下解决方案 1、更换relu ->tanh 或者其他激活函数 2、更改随机种子,估计是没有初始化好,或者调…...

Sqoop的使用
每个人的生活都是一个世界,即使最平凡的人也要为他那个世界的存在而战斗。 ——《平凡的世界》 目录 一、sqoop简介 1.1 导入流程 1.2 导出流程 二、使用sqoop 2.1 sqoop的常用参数 2.2 连接参数列表 2.3 操作hive表参数 2.4 其它参数 三、sqoop应用 - 导入…...

OpenGL ES 04 图片数据是怎么写入到对应纹理单元的
从指定路径加载图像并转换为 CGImage。获取图像的宽度和高度。创建一个 RGB 颜色空间。为图像数据分配内存。创建一个位图上下文并将图像绘制到上下文中。创建一个新的纹理对象并绑定到指定的纹理单元。指定二维纹理图像。释放分配的内存。设置纹理参数,包括放大和缩…...

C# 设计模式的六大原则(SOLID)
C# 设计模式的六大原则(SOLID) 引言 在面向对象编程中,设计模式提供了高效、可复用和可维护的代码结构。SOLID原则是软件设计中的一组重要原则,用于确保代码具有良好的可维护性、可扩展性和灵活性。SOLID是五个设计原则的首字母…...

数据库自增 id 过大导致前端时数据丢失
可以看到,前端响应参数是没有丢失精度的 但是在接受 axios 请求参数时出现了精度丢失 解决方案一:改变 axios 字符编码 axios.defaults.headers[Content-Type] application/json;charsetUTF-8; 未解决 解决方案二:手动使用 json.parse() …...

第二十六天 自然语言处理(NLP)词嵌入(Word2Vec、GloVe)
自然语言处理(NLP)中的词嵌入(Word2Vec、GloVe)技术,是NLP领域的重要组成部分,它们为词汇提供了高维空间到低维向量的映射,使得语义相似的词汇在向量空间中的距离更近。以下是对这些技术的详细解…...

MongoDB 固定集合
MongoDB 固定集合 MongoDB中的固定集合(Capped Collections)是一种具有固定大小的集合,当集合中的数据达到其最大大小时,它会自动覆盖最早的文档。这种类型的集合在MongoDB中用于实现高效的、固定大小的循环缓冲区。本文将详细介…...

数据结构9.3 - 文件基础(C++)
目录 1 打开文件字符读写关闭文件 上图源自:https://blog.csdn.net/LG1259156776/article/details/47035583 1 打开文件 法 1法 2ofstream file(path);ofstream file;file.open(path); #include<bits/stdc.h> using namespace std;int main() {char path[]…...

Leetcode 1254 Number of Closed Islands + Leetcode 1020 Number of Enclaves
Leetcode 1254 题意 给定一个m*n的矩阵含有0和1,1代表水,0代表陆地,岛屿是陆地的集合,如果一个岛屿和四个方向的边界相连,则不算封闭岛屿。求有多少个封闭的岛屿。 题目链接 https://leetcode.com/problems/number…...

Junit4单元测试快速上手
文章目录 POM依赖引入业务层测试代码Web层测试代码生成测试类文件 在工作中我用的最多的单元测试框架是Junit4。通常在写DAO、Service、Web层代码的时候都会进行单元测试,方便后续编码,前端甩锅。 POM依赖引入 <dependency><groupId>org.spr…...

U盘提示格式化?原因、恢复方案与预防措施全解析
一、U盘提示格式化现象概述 在日常使用U盘的过程中,我们有时会遇到一个令人头疼的问题——U盘插入电脑后,系统却弹出一个提示框,告知我们U盘需要格式化才能访问。这个提示往往伴随着数据的潜在丢失风险,让我们不禁为之心焦。U盘提…...

HTML——13.超链接
<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>超链接</title></head><body><!--超链接:从一个网页链接到另一个网页--><!--语法:<a href"淘宝网链接的地址"> 淘宝…...

vue中的设计模式
vue中使用了哪些设计模式 1. 观察者模式(Observer Pattern) 应用场景:Vue 的响应式系统核心就是观察者模式。 实现方式:通过 Object.defineProperty 或 Proxy 监听数据变化,当数据发生变化时,通知依赖的视…...

利用python将图片转换为pdf格式的多种方法,实现批量转换,内置模板代码,全网最全,超详细!!!
文章目录 前言1、img2pdf库的使用1.1 安装img2pdf库1.2 案例演示(模板代码) 2、Pillow库的使用2.1 pillow库的安装2.2 案例演示(模板代码) 3、PyMuPDF库的使用3.1 安装pymupdf库3.2 案例演示(模板代码)3.3 …...

tcpdump的常见方法
详解tcpdump的使用方法:网络数据包捕获与分析 tcpdump是一个功能强大的命令行工具,用于捕获和分析通过网络接口传输的数据包。它广泛应用于网络故障诊断、网络安全监控和协议分析等领域。本文将详细介绍tcpdump的使用方法,包括安装、基本命令…...

工控主板ESM7000/6800E支持远程桌面控制
英创公司ESM7000 是面向工业领域的双核 Cortex-A7 高性能嵌入式主板,ESM6800E则为单核Cortex-A7 高性价比嵌入式主板,ESM7000、ESM6800E都是公司的成熟产品,已广泛应用于工业很多领域。ESM7000/6800E板卡中Linux系统配置为linux-4.9.11内核、…...

wamp php7.4 运行dm8
背景 1、电脑安装了dm8,具体参照官网dm8安装 2、安装好了wamp,我当前的php版本切换成了7.4的,我wamp的安装路径d:\wamp64\ 操作 3、查看phpinfo,如果Thread Safet为enabled,则选择pdo74_dm.dll,否则选择…...

HTML5 进度条(Progress Bar)详解
HTML5 进度条(Progress Bar)详解 进度条是用于显示任务完成进度的控件,常用于加载、上传或下载等操作。HTML5提供了原生的<progress>元素,使得创建进度条变得简单和直观。 1. 基本用法 <progress>元素的基本语法如…...

LabVIEW开发中常见硬件通讯接口快速识别
在 LabVIEW 开发中,与硬件进行通讯是实现数据采集与控制的重要环节。准确判断通讯接口类型和协议,可以提高开发效率,减少调试时间。本文结合 LabVIEW 的实际应用,详细介绍如何识别和判断常见硬件通讯接口的定义,并提供…...

高频 SQL 50 题(基础版)_1068. 产品销售分析 I
销售表 Sales: (sale_id, year) 是销售表 Sales 的主键(具有唯一值的列的组合)。 product_id 是关联到产品表 Product 的外键(reference 列)。 该表的每一行显示 product_id 在某一年的销售情况。 注意: price 表示每…...

笔记:一次mysql主从复制延迟高的处理尝试
背景 mysql 5.7 主从复制 主库进行了一次灌数,导致多个大事务产生,主从延迟下不去,经确认该表最终truncate,并且该表仅有insert和select操作,故对该表的事务进行跳过,直到同步至truncate 跳过事务需谨慎&…...

基于C语言的卡丁车管理系统【控制台应用程序】
注意:需要提前创建对应的.dat文件 本项目实现了数据的永久存储,有用户的注册、登录。 管理员对卡丁车的管理、查看预约用户、修改帐户权限。 用户对个人信息的管理、查看并预约卡丁车、卡丁车维修上报。 维修员对卡丁车的维修状态上报、个人信息管理。 …...