如何在Flask应用程序中使用JSON Web Tokens进行安全认证

2024-04-22 19:20

本文主要是介绍如何在Flask应用程序中使用JSON Web Tokens进行安全认证,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

密码、信用卡信息、个人识别号码(PIN)——这些都是用于授权和认证的关键资产。这意味着它们需要受到未经授权的用户的保护。

作为开发者,我们的任务是保护这些敏感信息,并且在我们的应用程序中实施强大的安全措施非常重要。

现在,有许多认证机制可用于保护数据,如OAuth、OpenID Connect和JSON Web Tokens(JWTs)。

在本文中,我将向您展示如何通过在Flask应用程序中集成基于JWT的身份验证来使用JWTs来保护API中的信息。

以下是本文的内容:

  • 什么是JSON Web Token?
  • JWTs如何工作?
  • 如何使用JSON Web Tokens来认证Flask应用程序
    1. 安装依赖项
    2. 创建数据库和用户模型
    3. 配置应用程序以进行JWT身份验证
    4. 创建受保护的路由
    5. 创建登录功能
  • 结论

(本文视频讲解:java567.com)

先决条件

要按照本教程进行操作,您需要:

  • 理解HTTP方法
  • 理解如何在Flask中创建API
  • VS Code(或其他类似的)编辑器
  • 一个终端

什么是JSON Web Token?

JSON Web Tokens,简称JWTs,是一种用于在客户端和服务器之间安全传输信息的认证机制,使用JSON格式。

这些信息可以被验证和信任,因为它使用HMAC算法或使用RSA或ECDSA的公钥/私钥对进行数字签名。

令牌被编码为三部分,每部分由一个句点分隔,如下所示:

Header.Payload.Signature
  • **Header:**这定义了令牌的类型(JWT)和使用的签名算法。
  • **Payload:**这承载着用户特定的数据,如用户ID、用户名、角色和您想要包含的任何其他声明。此有效载荷被Base64编码以获得最大的安全性。
  • **Signature:**这是头部、有效载荷和服务器的秘密密钥的散列组合。它确保了令牌的完整性,并且任何对令牌的修改都将被检测到。

JWTs如何工作?

要理解JWTs如何工作,您需要知道令牌的作用。JWTs不是为了隐藏数据,而是为了确保正在发送的数据得到了认证。这就是为什么JWT被签名和编码,而不是加密。

JWT充当了从客户端向服务器传输数据的无状态手段。这意味着它不会在浏览器中存储任何会话对象,因此浏览器不会在请求之间保持会话状态。

而是,JWT使用一个令牌,在每次发出请求时都以请求头的形式发送。此令牌确认发送的令牌经过了认证,并允许访问该请求。

让我们看看这是如何发生的:

  1. 用户尝试登录并发送用户名和密码以由服务器验证。
  2. 验证函数执行检查,看看数据库中是否有匹配项。
  3. 一旦用户使用其信息(有效载荷)成功认证(登录),服务器就会生成一个JWT,并使用秘密密钥对其进行签名。
  4. 生成的JWT随每个请求头一起作为承载令牌发送,以检查用户是否被授权进行该请求。

如何在Flask应用程序中使用JSON Web Tokens进行身份验证

为了演示如何在Flask中实现JWT身份验证,我们将创建一个简单的应用程序,该应用程序使用JWT来处理登录功能和访问受保护的路由。

1. 安装依赖项

运行以下命令以安装我们需要的依赖项:

pip install flask flask-bcrypt Flask-JWT-Extended

接下来,请确保您导入依赖项并使用以下代码初始化您的Flask应用程序:

from flask import Flask, jsonify, session, request, redirect, url_for
from flask_jwt_extended import JWTManager, create_access_token, jwt_required, get_jwt_identity, get_jwtapp = Flask(__name__)////在这里编写主要代码if __name__ == "__main__":with app.app_context():app.run(debug=True)

2. 创建数据库和用户模型

为此,我们将使用SQL-Alchemy,它是一个Python SQL工具包,使在Python脚本中使用SQL变得不那么复杂。

要在应用程序中设置SQL Alchemy,请按照以下步骤操作:

首先,打开您的终端或命令提示符,并输入以下命令:

pip install sqlalchemy

此命令会在您的Python环境中安装SQLAlchemy,使其在项目目录中可用。

接下来,配置您的应用程序以使用您首选的数据库管理系统(DBMS)。本教程将使用SQlite3 DBMS,因为它不需要单独的服务器:

app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///site.db'

此代码片段指示Flask-SQLAlchemy在您的项目目录中创建并使用site.db文件作为应用程序的SQLite数据库。

然后在您的应用程序中初始化数据库:

db = SQLAlchemy(app)

这个数据库的实例充当应用程序和数据库之间的桥梁。

现在创建User模型,我们将在本教程中存储用户的详细信息:

class User(db.Model, UserMixin):id = db.Column(db.Integer, primary_key=True)username = db.Column(db.String(20), unique=True, nullable=False)password = db.Column(db.String(80), nullable=False)is_active = db.Column(db.Boolean(), default=True)cart = db.Column(JSON, nullable=True, default=list)  # Make cart nullable# Define the relationship between User and CartProductscart_products = relationship('CartProducts', backref="user", lazy="dynamic")# Define the relationship between User and Wishlistswishlists = db.relationship('Wishlists', backref='user', lazy=True)def __repr__(self):return f'<User {self.username}>'

**注意:**您可以使用相同的语法创建其他模型,以表示应用程序中的不同数据实体。

3. 配置应用程序以进行JWT身份验证

要在您的Flask应用程序中实现JWT身份验证,请导入必要的库并使用以下代码设置适当的配置:

from flask import Flask, jsonify, request
from flask_sqlalchemy import SQLAlchemy
from flask_jwt_extended import JWTManager, create_access_token, jwt_requiredapp = Flask(__name__)# 配置
app.config['SECRET_KEY'] = 'your_strong_secret_key'
app.config["JWT_SECRET_KEY"] = 'your_jwt_secret_key'
app.config['JWT_TOKEN_LOCATION'] = ['headers']# 数据库初始化
db = SQLAlchemy(app)# JWT初始化
jwt = JWTManager(app)# 应用程序的其他代码(路由等)

此代码片段导入了我们应用程序所需的以下组件:

  • app.config[‘SECRET_KEY’] 设置Flask应用程序的秘密密钥,用于安全地签名会话cookie和其他安全相关需求。
  • app.config[‘JWT_SECRET_KEY’] 设置用于对Flask-JWT操作中的JWT进行编码和解码的秘密密钥。
  • app.config[‘JWT_TOKEN_LOCATION’] 指定应用程序应在何处查找JWT。在这里,它设置为在HTTP标头中查找。

一旦我们设置了这些,我们就可以创建我们打算保护的端点和路由了。

4. 创建受保护的路由

受保护的路由是我们打算对未经授权的用户隐藏的页面。

例如,假设我们试图进入一个只允许社会成员进入的场所。但是,一名保安正在阻止“未经授权的用户”像我们这样进入场所。在这种情况下,我们是应用程序的用户,场所是我们正在保护的URL,保安是一个**@jwt_required**装饰器。

**@jwt_required**装饰器用于保护需要身份验证的特定路由。此装饰器将在允许访问页面之前确认请求标头中是否有JWT访问令牌:

@app.route('/get_name', methods=['GET'])
@jwt_required()
def get_name():# 从JWT中提取用户IDuser_id = get_jwt_identity()user = User.query.filter_by(id=user_id).first()# 检查用户是否存在if user:return jsonify({'message': 'User found', 'name': user.name})else:return jsonify({'message': 'User not found'}), 404

在此代码片段中,我们创建了一个函数,在身份验证后返回用户的名称。如果缺少令牌、令牌无效或过期,请求将被拒绝,并且通常服务器将返回HTTP 401 Unauthorized状态。

5. 创建登录页面

在此端点中,我们将创建一个函数,该函数从客户端请求(例如,表单数据)接受用户名和密码凭据,并将从用户获取的凭据与数据库中的用户数据进行比较。如果匹配成功,将生成包含用户信息的JWT访问令牌。

@app.route('/login', methods=['POST'])
def login():data = request.get_json()username = data['username']password = data['password']print('Received data:', username , password)user = User.query.filter_by(username=username).first()if user and bcrypt.check_password_hash(user.password, password):access_token = create_access_token(identity=user.id)return jsonify({'message': 'Login Success', 'access_token': access_token})else:return jsonify({'message': 'Login Failed'}), 401

在此示例中,当收到POST请求时,函数使用bcrypt对用户的凭据与数据库进行安全密码验证。如果凭据有效,服务器将为用户生成JWT,允许他们访问受保护的路由。

这是一个示例React表单,将POST请求发送到登录端点:

import React from "react";
import axios from "axios";
import { useState } from "react";
import Footer from "./Footer";
// import "./Login.css";function Login() {const [password, setPassword] = useState("");const [username, setUsername] = useState("");const handleLogin = async (event) => {event.preventDefault();const data = {username: username,Password: password,};try {const response = await axios.post("http://localhost:5000/login", {username,password,});localStorage.setItem("access_token", response.data.access_token);// Redirect to protected routealert("Login successful");} catch (error) {console.error(error);// Display error message to user}};const handleUsernameChange = (event) => {setUsername(event.target.value);};const handlePasswordChange = (event) => {setPassword(event.target.value);};return (<div ><form method="post" ><inputtype="text"id=""placeholder="Username"name="username"requiredvalue={username}onChange={handleUsernameChange}/><inputtype="text"id=""placeholder="Your email"/><inputtype="password"requiredplaceholder="Your Password"name="password"value={password}onChange={handlePasswordChange}/></form><button type="submit" onClick={handleLogin}>Log In</button></div>);}export default Login;

在此React组件中,我们提供了一个登录表单,该表单使用Axios将POST请求发送到登录端点。它使用React的useState钩子管理用户名和密码输入,并在提交表单后提交这些值。

如果登录成功,它会将JWT存储在本地存储中。这使得客户端应用程序在向服务器发出经过身份验证的请求时可以轻松地检索令牌。

jwtDemo-1

结论

在本文中,我们学习了如何在Flask中使用JSON Web Tokens来保护API。我们介绍了JWT的基础知识,它们的工作原理,并提供了一个逐步的过程来实现这种身份验证方法。这包括安装必要的依赖项,创建用户模型和保护路由等内容。

您可以在此基础上构建更多功能,例如添加刷新令牌、与第三方OAuth提供程序集成或处理更复杂的用户权限。

(本文视频讲解:java567.com)

这篇关于如何在Flask应用程序中使用JSON Web Tokens进行安全认证的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


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

相关文章

Linux系统之lvcreate命令使用解读

《Linux系统之lvcreate命令使用解读》lvcreate是LVM中创建逻辑卷的核心命令,支持线性、条带化、RAID、镜像、快照、瘦池和缓存池等多种类型,实现灵活存储资源管理,需注意空间分配、R... 目录lvcreate命令详解一、命令概述二、语法格式三、核心功能四、选项详解五、使用示例1. 创建逻

在Java中使用OpenCV实践

《在Java中使用OpenCV实践》用户分享了在Java项目中集成OpenCV4.10.0的实践经验,涵盖库简介、Windows安装、依赖配置及灰度图测试,强调其在图像处理领域的多功能性,并计划后续探... 目录前言一 、OpenCV1.简介2.下载与安装3.目录说明二、在Java项目中使用三 、测试1.测

Python Web框架Flask、Streamlit、FastAPI示例详解

《PythonWeb框架Flask、Streamlit、FastAPI示例详解》本文对比分析了Flask、Streamlit和FastAPI三大PythonWeb框架:Flask轻量灵活适合传统应用... 目录概述Flask详解Flask简介安装和基础配置核心概念路由和视图模板系统数据库集成实际示例Stre

C++中detach的作用、使用场景及注意事项

《C++中detach的作用、使用场景及注意事项》关于C++中的detach,它主要涉及多线程编程中的线程管理,理解detach的作用、使用场景以及注意事项,对于写出高效、安全的多线程程序至关重要,下... 目录一、什么是join()?它的作用是什么?类比一下:二、join()的作用总结三、join()怎么

mybatis中resultMap的association及collectio的使用详解

《mybatis中resultMap的association及collectio的使用详解》MyBatis的resultMap定义数据库结果到Java对象的映射规则,包含id、type等属性,子元素需... 目录1.reusltmap的说明2.association的使用3.collection的使用4.总

详解MySQL中JSON数据类型用法及与传统JSON字符串对比

《详解MySQL中JSON数据类型用法及与传统JSON字符串对比》MySQL从5.7版本开始引入了JSON数据类型,专门用于存储JSON格式的数据,本文将为大家简单介绍一下MySQL中JSON数据类型... 目录前言基本用法jsON数据类型 vs 传统JSON字符串1. 存储方式2. 查询方式对比3. 索引

Spring Boot配置和使用两个数据源的实现步骤

《SpringBoot配置和使用两个数据源的实现步骤》本文详解SpringBoot配置双数据源方法,包含配置文件设置、Bean创建、事务管理器配置及@Qualifier注解使用,强调主数据源标记、代... 目录Spring Boot配置和使用两个数据源技术背景实现步骤1. 配置数据源信息2. 创建数据源Be

Java中使用 @Builder 注解的简单示例

《Java中使用@Builder注解的简单示例》@Builder简化构建但存在复杂性,需配合其他注解,导致可变性、抽象类型处理难题,链式编程非最佳实践,适合长期对象,避免与@Data混用,改用@G... 目录一、案例二、不足之处大多数同学使用 @Builder 无非就是为了链式编程,然而 @Builder

在MySQL中实现冷热数据分离的方法及使用场景底层原理解析

《在MySQL中实现冷热数据分离的方法及使用场景底层原理解析》MySQL冷热数据分离通过分表/分区策略、数据归档和索引优化,将频繁访问的热数据与冷数据分开存储,提升查询效率并降低存储成本,适用于高并发... 目录实现冷热数据分离1. 分表策略2. 使用分区表3. 数据归档与迁移在mysql中实现冷热数据分

C#解析JSON数据全攻略指南

《C#解析JSON数据全攻略指南》这篇文章主要为大家详细介绍了使用C#解析JSON数据全攻略指南,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、为什么jsON是C#开发必修课?二、四步搞定网络JSON数据1. 获取数据 - HttpClient最佳实践2. 动态解析 - 快速