前端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"淘宝网链接的地址"> 淘宝…...
从PUMA560到你的项目:手把手教你将经典DH建模流程迁移到自定义机械臂
从PUMA560到自定义机械臂:DH建模实战迁移指南 当机械臂从教科书案例走向真实项目时,最令人头疼的莫过于面对一个全新构型却不知如何下手。本文将以工业界经典的PUMA560为跳板,拆解一套可迁移的DH建模方法论,带您跨越从理论到实践的…...
RAG 系列(十七):Agentic RAG——让 Agent 主导检索过程
Pipeline RAG 的沉默失败 前面十几篇一直在优化一件事:怎么让检索结果更好。更好的分块、更精准的排序、更聪明的问法、CRAG 纠偏、Graph RAG 关系遍历…… 但有一件事始终没变:无论检索结果好不好,都会被传给 LLM 生成答案。 Pipeline RAG 的流程是线性的、固定的: 问…...
终极CoreCycler教程:简单三步完成CPU稳定性测试与优化
终极CoreCycler教程:简单三步完成CPU稳定性测试与优化 【免费下载链接】corecycler Script to test single core stability, e.g. for PBO & Curve Optimizer on AMD Ryzen or overclocking/undervolting on Intel processors 项目地址: https://gitcode.com/…...
3大突破性功能:如何用QtScrcpy彻底改变你的Android投屏体验
3大突破性功能:如何用QtScrcpy彻底改变你的Android投屏体验 【免费下载链接】QtScrcpy Android real-time display control software 项目地址: https://gitcode.com/GitHub_Trending/qt/QtScrcpy 你是否曾经为了在电脑上操作手机而烦恼?无论是游…...
别再死记硬背公式了!用Python+NumPy手把手带你仿真RLC串联谐振(附代码)
用PythonNumPy动态仿真RLC串联谐振:告别枯燥公式,直观理解电路本质 当你第一次翻开电路分析教材,看到那些密密麻麻的公式推导和抽象的频率响应曲线时,是否感到一阵眩晕?RLC串联谐振作为电路分析的核心概念,…...
STM32CubeIDE实战指南:从代码编译到一键下载的完整流程解析
1. STM32CubeIDE开发环境概述 对于刚接触STM32开发的工程师来说,选择一款合适的集成开发环境(IDE)至关重要。STM32CubeIDE是ST官方推出的免费开发工具,它集成了代码编辑、编译、调试和下载功能于一体,特别适合新手快速上手。我在实际项目中使…...
ViGEmBus终极指南:Windows游戏手柄模拟驱动的完整解决方案
ViGEmBus终极指南:Windows游戏手柄模拟驱动的完整解决方案 【免费下载链接】ViGEmBus Windows kernel-mode driver emulating well-known USB game controllers. 项目地址: https://gitcode.com/gh_mirrors/vi/ViGEmBus 你是否曾经遇到过这样的情况ÿ…...
Python与ChatGPT构建智能办公自动化:从任务分解到智能体系统
1. 项目概述:用Python与ChatGPT联手,让办公自动化“开口说话”如果你每天还在重复着打开Excel、复制粘贴数据、手动写邮件、整理报告这些枯燥的活儿,那这个项目可能就是你的“数字员工”入职通知书。Sven-Bo/automate-office-tasks-using-cha…...
Go语言静态站点生成器Zeuxis:极简架构与高性能构建实践
1. 项目概述:一个轻量级、高性能的静态站点生成器最近在折腾个人博客和文档站点,发现市面上的静态站点生成器虽然多,但要么配置复杂、学习曲线陡峭,要么过于臃肿,启动和构建速度慢得让人抓狂。直到我遇到了bnomei/zeux…...
模拟电路布局优化:多智能体强化学习实践
1. 模拟电路布局优化的挑战与机遇在集成电路设计领域,模拟电路布局一直是个令人头疼的问题。作为一名从业十余年的模拟电路设计师,我深刻体会到传统布局方法在面对现代工艺挑战时的局限性。每次手工调整晶体管位置时,那种"差之毫厘&…...
