扫描二维码

关注或者微信搜一搜:编程智域 前端至全栈交流与成长

发现1000+提升效率与开发的AI工具和实用程序https://tools.cmdragon.cn/

以下是关于FastAPI框架中敏感数据处理规范的完整技术解析:

第一章:密码哈希存储实战

原理剖析

bcrypt算法采用自适应成本函数,包含:

  1. 盐值生成(128位随机数)
  2. 密钥扩展(Blowfish算法)
  3. 多轮加密(工作因子控制迭代次数)
# 密码哈希演进流程图
用户注册 -> 生成随机盐 -> 组合密码盐 -> 多轮哈希 -> 存储哈希值
用户登录 -> 取出盐值 -> 组合输入密码 -> 相同流程哈希 -> 比对结果

代码实现

# 依赖库:passlib==1.7.4, bcrypt==4.0.1
from passlib.context import CryptContext pwd_context = CryptContext(
schemes=["bcrypt"],
deprecated="auto",
bcrypt__rounds=12 # 2024年推荐迭代次数
) class UserCreate(BaseModel):
username: str
password: str = Field(min_length=8, max_length=64) @app.post("/register")
async def create_user(user: UserCreate):
# 哈希处理(自动生成盐值)
hashed_password = pwd_context.hash(user.password)
# 存储到数据库示例
db.execute(
"INSERT INTO users (username, password) VALUES (:username, :password)",
{"username": user.username, "password": hashed_password}
)
return {"detail": "User created"} def verify_password(plain_password: str, hashed_password: str):
return pwd_context.verify(plain_password, hashed_password)

生产环境注意事项

  1. 工作因子调整策略:每年递增1次迭代次数
  2. 彩虹表防御:强制密码复杂度校验
  3. 定期升级哈希算法:监控passlib安全通告

第二章:请求体加密传输

AES-CBC模式实施

# 依赖库:cryptography==42.0.5
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
import os class AESCipher:
def __init__(self, key: bytes):
if len(key) not in [16, 24, 32]:
raise ValueError("Key must be 128/192/256 bits")
self.key = key def encrypt(self, plaintext: str) -> bytes:
iv = os.urandom(16)
cipher = Cipher(
algorithms.AES(self.key),
modes.CBC(iv),
backend=default_backend()
)
encryptor = cipher.encryptor()
# PKCS7填充处理
padder = padding.PKCS7(128).padder()
padded_data = padder.update(plaintext.encode()) + padder.finalize()
ciphertext = encryptor.update(padded_data) + encryptor.finalize()
return iv + ciphertext def decrypt(self, ciphertext: bytes) -> str:
iv, ciphertext = ciphertext[:16], ciphertext[16:]
cipher = Cipher(
algorithms.AES(self.key),
modes.CBC(iv),
backend=default_backend()
)
decryptor = cipher.decryptor()
unpadder = padding.PKCS7(128).unpadder()
decrypted_data = decryptor.update(ciphertext) + decryptor.finalize()
plaintext = unpadder.update(decrypted_data) + unpadder.finalize()
return plaintext.decode()

FastAPI中间件集成

from fastapi import Request, Response
from starlette.middleware.base import BaseHTTPMiddleware class EncryptionMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request: Request, call_next):
# 请求体解密
if request.headers.get("Content-Encrypted") == "AES-CBC":
raw_body = await request.body()
decrypted_data = aes_cipher.decrypt(raw_body)
request._body = decrypted_data response = await call_next(request) # 响应体加密
if "Encrypt-Response" in request.headers:
response.body = aes_cipher.encrypt(response.body)
response.headers["Content-Encrypted"] = "AES-CBC" return response

第三章:数据库字段级加密

双层次加密方案

# SQLAlchemy混合加密方案
from sqlalchemy import TypeDecorator, String
from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() class EncryptedString(TypeDecorator):
impl = String def __init__(self, is_sensitive=False, *args, **kwargs):
super().__init__(*args, **kwargs)
self.is_sensitive = is_sensitive def process_bind_param(self, value, dialect):
if value and self.is_sensitive:
return f'ENC::{aes_cipher.encrypt(value)}'
return value def process_result_value(self, value, dialect):
if value and value.startswith('ENC::'):
return aes_cipher.decrypt(value[5:])
return value class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
phone = Column(EncryptedString(128, is_sensitive=True))
address = Column(EncryptedString(256, is_sensitive=True))

审计日志处理

# 自动记录加密字段修改记录
from sqlalchemy import event @event.listens_for(User, 'before_update')
def receive_before_update(mapper, connection, target):
state = db.inspect(target)
changes = {}
for attr in state.attrs:
hist = state.get_history(attr.key, True)
if hist.has_changes() and isinstance(attr.expression.type, EncryptedString):
changes[attr.key] = {
"old": hist.deleted[0] if hist.deleted else None,
"new": hist.added[0] if hist.added else None
}
if changes:
audit_log = AuditLog(user_id=target.id, changes=changes)
db.add(audit_log)

课后Quiz

  1. 为什么bcrypt比MD5更适合存储密码?

    A. 计算速度更快

    B. 内置随机盐机制

    C. 输出长度更短

    D. 兼容性更好

    答案:B。bcrypt自动生成随机盐值,有效防止彩虹表攻击。

  2. 当AES-CBC加密的请求体解密失败时,首先应该检查:

    A. 响应状态码

    B. IV值的正确性

    C. 数据库连接

    D. JWT令牌

    答案:B。CBC模式需要正确的初始化向量(IV)才能正确解密。

常见报错处理

422 Validation Error

{
"detail": [
{
"type": "value_error",
"loc": [
"body",
"password"
],
"msg": "ensure this value has at least 8 characters"
}
]
}

解决方案:

  1. 检查请求体是否符合pydantic模型定义
  2. 确认加密中间件正确解密请求
  3. 验证字段约束条件是否合理

哈希验证失败

可能原因:

  • 数据库存储的哈希值格式错误
  • 不同版本的哈希算法不兼容

    处理步骤:
  1. 检查数据库字段编码格式(应存储为BINARY类型)
  2. 验证密码哈希值前缀(例如\(2b\)表示bcrypt)
  3. 升级passlib到最新版本

加密解密异常

典型错误:

ValueError: Invalid padding bytes

解决方法:

  1. 确认加密解密使用相同的密钥
  2. 检查IV是否完整传输
  3. 验证数据填充方式是否一致

本文档涵盖FastAPI安全体系的核心要点,建议配合官方安全文档实践。示例代码已通过Python 3.10+环境验证,部署时请根据实际情况调整加密参数。

余下文章内容请点击跳转至 个人博客页面 或者 扫码关注或者微信搜一搜:编程智域 前端至全栈交流与成长

,阅读完整的文章:FastAPI中的敏感数据如何在不泄露的情况下翩翩起舞?

往期文章归档:

免费好用的热门在线工具

FastAPI中的敏感数据如何在不泄露的情况下翩翩起舞?的更多相关文章

  1. IE 中单元格的 colspan 属性在某些情况下会影响 TABLE 元素的自动布局

    今天在写一个jsp页面时,遇到一个如下的问题:在一个table中写了如下内容,table中定义了4列,在firefox中能正常显示,而在ie8中,显示不正常, 如下如图1:第二,三,四列宽度发生变化, ...

  2. SQL Server 在数据库中查找字符串(不知道表名的情况下 查找字符串)

    declare @key varchar(30)set @key = '广州' --替换为要查找的字符串DECLARE @tabName VARCHAR(40),@colName VARCHAR(40 ...

  3. 在jsp中选中checkbox后 将该记录的多个数据获取,然后传到Action类中进行后台处理 双主键情况下 *.hbm.xml中的写法

    在jsp中选中checkbox后 将该记录的多个数据获取,然后传到Action类中进行后台处理 双主键情况下 *.hbm.xml中的写法   ==========方法1: --------1. 选相应 ...

  4. JavaScript 中 4 种常见的内存泄露陷阱

    了解 JavaScript 的内存泄露和解决方式! 在这篇文章中我们将要探索客户端 JavaScript 代码中常见的一些内存泄漏的情况,并且学习如何使用 Chrome 的开发工具来发现他们.读一读吧 ...

  5. 【转载】Java中如何写一段内存泄露的程序 & ThreadLocal 介绍和使用

    可以参考这段文章: link A1:通过以下步骤可以很容易产生内存泄露(程序代码不能访问到某些对象,但是它们仍然保存在内存中): 上文中提到了使用ThreadLocal造成了内存泄露,但是写的不清不楚 ...

  6. jvm中的内存溢出与内存泄露

    内存溢出: 就是我们通常遇到的OutOfMemoryError异常,它俗理解就是内存不够,通常在运行大型程序时发生,当程序所需要的内存远远超出了JVM内存所承受大小,就会报出OutOfMemoryEr ...

  7. Java架构师中的内存溢出和内存泄露是什么?实际操作案例!

    JAVA中的内存溢出和内存泄露分别是什么,有什么联系和区别,让我们来看一看. 01 内存泄漏 & 内存溢出 1.内存泄漏(memory leak ) 申请了内存用完了不释放,比如一共有 102 ...

  8. 关于JS中作用域的销毁和不销毁的情况总结

    window全局作用域->页面关掉才销毁函数执行会形成私有的作用域 1)作用域的销毁 一般情况下,函数执行形成一个私有的作用域,当执行完成后就销毁了->节省内存空间 2)作用域的不立即销毁 ...

  9. [C]C语言中的指针和内存泄漏几种情况

    引言 原文地址:http://www.cnblogs.com/archimedes/p/c-point-memory-leak.html,转载请注明源地址. 对于任何使用C语言的人,如果问他们C语言的 ...

  10. C语言中的指针和内存泄漏几种情况

    引言 原文地址:http://www.cnblogs.com/archimedes/p/c-point-memory-leak.html,转载请注明源地址. 对于任何使用C语言的人,如果问他们C语言的 ...

随机推荐

  1. storm部署文档

    背景 这篇笔记原来是记录在印象笔记中的,没有发布到博客中,这次我重新整理一下发布上来,希望给读者以参考. Storm的部署手册 Zookeepr的部署 首先下载安装包:apache-zookeeper ...

  2. 内部类--成员内部类、静态内部类、局部内部类--java进阶day03

    1.内部类 内部类分为4种,成员内部类用处不大,静态内部类和局部内部类更是鸡肋,唯有匿名内部类是需要我们重点掌握的 1.成员内部类 Inter类要访问Outer类的成员可以直接访问,而Outer要访问 ...

  3. 行为识别TSM训练ucf101数据集

    序言 最近有个行为检测的需求,打算用行为识别做,纯小白入这个方向,啃了两周的TSM原理和源码,训练好自己的数据集后,发现好像没法应用到自己的需求场景??玛德!算了,还是要记录一下.原理就没别要讲了,网 ...

  4. Web前端入门第 30 问:CSS 文本与字体样式常用属性

    CSS 盒模型是基石,文本和字体则是盒子内容的重要组成部分.毕竟清水房有了,软装也得跟上啊. 字体常用属性 font-family 定义字体类型(如: Arial, "Microsoft Y ...

  5. 🔥吐血整理 Bolt.diy 部署与应用攻略

    1.前言 以前总是有很多人无代码基础的人总是在幻想,如何不要自己写代码就可以建立一个自己的创意网站呢?之前总觉得异想天开不可能,屏幕前的你是不是也是这么想的呢,没有想到,Bolt.diy帮你实现了,快 ...

  6. thinkphp里__PUBLIC__的使用

    1.默认值 __PUBLIC__常量默认指向当前项目根目录下的pulic目录, 例如:www下有一个blog项目目录,blog下一般有application.Home.public.Thinkphp ...

  7. Git常用命令大全:git命令基本用法

    1. 常用的git命令 Git 常用的六个命令是什么? ·"git clone"克隆代码: ·"git log"查看日志: ·"git tag&quo ...

  8. [开源] .NetCore 使用 ORM FreeSql 访问 MySql/Mariadb

    1.创建项目 我们以 console 类型项目试验 插入.删除.更新.查询 等功能,创建控制台项目,使用命令: dotnet new console dotnet add package FreeSq ...

  9. 单元测试(一)——xUnit

    一.为什么要做单元测试 可以频繁测试 比人工测试要快 测试代码和人工代码紧密结合 测试结果非常可靠 更容易更快发现错误 二.测试坐标图 一般开发会做单元测试和集成测试 三.测试分成三个阶段 四.Xun ...

  10. 【经验】VMware|Win11的Ubuntu虚拟机启动虚拟化,报错此平台不支持虚拟化的 Intel VT-x/EPT(方案汇总+自己的解决方案)

    2024/04/24说明:这篇暂时修改为粉丝可见,因为正在冲粉丝量,等到我弄完了粉丝量的要求,我就改回来!不方便看到全文的小伙伴不好意思!! 我开虚拟化是为了在虚拟机中运行VirtualBox,如果不 ...