如何让前端安全直传大文件至Azure Blob Storage?规避Django中转超时
安全实现前端直传Azure Blob Storage的方案
当然有安全的方式,核心思路是让后端生成临时、受限权限的访问凭证,前端用这个凭证直接上传,完全绕开后端中转,既解决超时问题,又不会暴露存储账户的敏感信息。下面是两种主流方案及具体实现:
一、使用SAS令牌(最常用)
SAS(共享访问签名)是Azure提供的一种临时授权机制,后端可以生成仅允许特定操作(比如上传指定Blob)、短有效期的令牌,前端拿到后直接用它访问Blob存储。
1. Django后端生成SAS令牌
首先确保后端已安装azure-storage-blob库:
pip install azure-storage-blob
后端代码示例(结合Django身份验证,仅授权用户可获取令牌):
from azure.storage.blob import generate_blob_sas, BlobSasPermissions from datetime import datetime, timedelta from django.http import JsonResponse from django.contrib.auth.decorators import login_required import os @login_required def get_upload_sas(request): # 从环境变量读取存储信息,绝对不要硬编码密钥! storage_account = os.environ.get("AZURE_STORAGE_ACCOUNT") storage_key = os.environ.get("AZURE_STORAGE_KEY") container_name = "user-uploads" # 生成唯一Blob名称,避免重名(结合用户ID、时间戳和原文件名) filename = request.GET.get("filename") blob_name = f"user_{request.user.id}/{datetime.utcnow().strftime('%Y%m%d_%H%M%S')}_{filename}" # 生成SAS令牌:仅允许创建/写入,有效期1小时,限制操作范围 sas_token = generate_blob_sas( account_name=storage_account, container_name=container_name, blob_name=blob_name, account_key=storage_key, permission=BlobSasPermissions(create=True, write=True), expiry=datetime.utcnow() + timedelta(hours=1), # 可选:限制仅允许用户的IP上传(需根据实际场景配置) # ip_range="192.168.1.0-192.168.1.255" ) upload_url = f"https://{storage_account}.blob.core.windows.net/{container_name}/{blob_name}?{sas_token}" return JsonResponse({"upload_url": upload_url, "blob_name": blob_name})
2. 前端用SAS令牌直传
拿到后端返回的upload_url后,直接用Fetch或Azure JS SDK上传,大文件建议分块上传避免超时:
基础Fetch上传:
async function uploadFile(file) { // 请求后端获取上传凭证 const authRes = await fetch(`/get-upload-sas?filename=${encodeURIComponent(file.name)}`, { credentials: "include" // 携带Django会话Cookie,确保用户已登录 }); const { upload_url } = await authRes.json(); // 上传文件到Blob存储 const uploadRes = await fetch(upload_url, { method: "PUT", body: file, headers: { "Content-Type": file.type } }); if (uploadRes.ok) { console.log("文件上传成功"); // 可选:通知后端上传完成,记录Blob元数据/关联用户 await fetch("/upload-finish", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ filename: file.name, blob_path: upload_url.split("?")[0] }) }); } else { console.error("上传失败", await uploadRes.text()); } }
大文件分块上传(用Azure JS SDK):
先安装SDK:
npm install @azure/storage-blob
代码示例:
import { BlockBlobClient } from "@azure/storage-blob"; async function uploadLargeFile(file, uploadUrl) { const blobClient = new BlockBlobClient(uploadUrl); // 分块上传:每块8MB,支持断点续传 await blobClient.uploadBrowserData(file, { blockSize: 8 * 1024 * 1024, // 8MB每块 concurrency: 3 // 并发上传3个块 }); console.log("大文件上传完成"); }
二、使用Azure AD OAuth2令牌(企业场景)
如果你的系统已经集成Azure AD身份验证,可以用OAuth2令牌授权前端上传:
- 后端引导用户完成Azure AD登录,获取针对
Storage Blob Data Contributor权限的访问令牌 - 前端用这个令牌调用Azure Blob Storage的API上传文件
- 优势:无需管理SAS令牌,完全依赖Azure AD的身份体系,权限控制更精细
关键安全注意事项
- 绝对不能暴露存储账户密钥:所有敏感信息必须存在后端环境变量或配置文件中,前端只能拿到临时凭证
- 严格限制SAS权限:只给必要的权限(比如仅
create/write,不要给read/delete),有效期设短(比如1小时内) - 后端前置验证:生成SAS前必须验证用户的上传权限(比如用户是否有权上传该类型文件、存储空间是否足够)
- Blob命名规则:用用户ID、时间戳等生成唯一Blob名称,避免恶意覆盖或重名
- 上传后校验:前端上传完成后,后端可以主动验证Blob是否存在、文件大小是否符合要求,确保上传完整性
内容的提问来源于stack exchange,提问作者user55665484375
相关产品推荐
相关产品推荐

