Azure Blob存储Blob项SAS访问令牌生成及读写问题排查
问题:Azure Blob存储Word文件的读写SAS令牌生成及代码故障排查
我是Azure平台新手,需要为Azure Blob存储中的Word文件生成带读写权限的SAS访问令牌。业务场景是用户提交数据后,我接收数据转成字符串数组,写入Blob里的表单文件。已经实现表单更新逻辑,但SAS生成和Blob读写代码无法正常运行,相关代码如下:
async static Task<Uri> GetUserDelegationSasBlob(BlobClient blobClient) { BlobServiceClient blobServiceClient = blobClient.GetParentBlobContainerClient().GetParentBlobServiceClient(); // 获取用户委托密钥 Azure.Storage.Blobs.Models.UserDelegationKey userDelegationKey = await blobServiceClient.GetUserDelegationKeyAsync(DateTimeOffset.UtcNow, DateTimeOffset.UtcNow.AddDays(7)); // 创建SAS令牌 BlobSasBuilder sasBuilder = new BlobSasBuilder() { BlobContainerName = blobClient.BlobContainerName, BlobName = blobClient.Name, Resource = "b", StartsOn = DateTimeOffset.UtcNow, ExpiresOn = DateTimeOffset.UtcNow.AddDays(7) }; // 指定SAS的读写权限 sasBuilder.SetPermissions(BlobSasPermissions.Read | BlobSasPermissions.Write); // 为Blob URI添加SAS令牌 BlobUriBuilder blobUriBuilder = new BlobUriBuilder(blobClient.Uri) { Sas = sasBuilder.ToSasQueryParameters(userDelegationKey, blobServiceClient.AccountName) }; Console.WriteLine("Blob用户委托SAS URI: {0}", blobUriBuilder); Console.WriteLine(); return blobUriBuilder.ToUri(); } static async Task ReadBlobWithSasAsync(Uri sasUri) { // 读取文件内容 public static void Run(Stream myBlob, string fileContent) { StreamReader contentReader = new StreamReader(myBlob); string sampleContent = contentReader.ReadToEnd(); char[] spearator = { ' ' }; string[] content = sampleContent.Split(spearator); reader.FillForm(content); } // 创建Blob客户端用于操作 BlobClient blobClient = new BlobClient(sasUri, null); // 下载并读取Blob内容 try { Console.WriteLine("Blob内容:"); // 下载Blob内容到流并读取 BlobDownloadInfo blobDownloadInfo = await blobClient.DownloadAsync(); using (StreamReader reader = new StreamReader(blobDownloadInfo.Content, true)) { string line; while ((line = reader.ReadLine()) != null) { Console.WriteLine(line); } } Console.WriteLine(); Console.WriteLine("SAS {0} 读取操作成功", sasUri); Console.WriteLine(); } catch (RequestFailedException e) { // 检查403(禁止访问)错误,SAS无效时Azure Storage会返回该错误 if (e.Status == 403) { Console.WriteLine("SAS {0} 读取操作失败", sasUri); Console.WriteLine("额外错误信息: " + e.Message); Console.WriteLine(); } else { Console.WriteLine(e.Message); Console.ReadLine(); throw; } } }
代码问题分析
- 语法错误:
ReadBlobWithSasAsync方法内部嵌套了Run方法,C#不允许方法嵌套,直接导致编译失败。需将Run方法移到外部或整合逻辑。 - Word文件解析错误:用
StreamReader直接读取.docx文件(二进制格式)会得到乱码,无法正确解析成字符串数组,需用专门的Office文档处理库。 - 权限风险:使用用户委托SAS需当前身份具备
Microsoft.Storage/storageAccounts/blobServices/generateUserDelegationKey/action权限,权限不足会导致密钥获取失败,生成无效SAS。 - 逻辑冗余:
ReadBlobWithSasAsync同时包含Blob下载和独立的流读取逻辑,结构混乱,需合并或拆分。
修正后的代码示例
1. 正确生成用户委托SAS的方法
async static Task<Uri> GetUserDelegationSasBlob(BlobClient blobClient) { BlobServiceClient blobServiceClient = blobClient.GetParentBlobContainerClient().GetParentBlobServiceClient(); // 获取用户委托密钥(有效期7天) UserDelegationKey userDelegationKey = await blobServiceClient.GetUserDelegationKeyAsync(DateTimeOffset.UtcNow, DateTimeOffset.UtcNow.AddDays(7)); // 构建SAS令牌 BlobSasBuilder sasBuilder = new BlobSasBuilder() { BlobContainerName = blobClient.BlobContainerName, BlobName = blobClient.Name, Resource = "b", // 指定为Blob资源 StartsOn = DateTimeOffset.UtcNow, ExpiresOn = DateTimeOffset.UtcNow.AddDays(7) }; // 设置读写权限 sasBuilder.SetPermissions(BlobSasPermissions.Read | BlobSasPermissions.Write); // 生成带SAS的Blob URI BlobUriBuilder blobUriBuilder = new BlobUriBuilder(blobClient.Uri) { Sas = sasBuilder.ToSasQueryParameters(userDelegationKey, blobServiceClient.AccountName) }; Console.WriteLine("Blob用户委托SAS URI: {0}", blobUriBuilder); return blobUriBuilder.ToUri(); }
2. 修正后的Word文件读取处理方法
需先安装DocumentFormat.OpenXml NuGet包用于解析.docx文件:
using DocumentFormat.OpenXml.Packaging; using DocumentFormat.OpenXml.Wordprocessing; static async Task ProcessWordBlobWithSasAsync(Uri sasUri) { BlobClient blobClient = new BlobClient(sasUri); try { // 下载Blob到内存流 BlobDownloadInfo downloadInfo = await blobClient.DownloadAsync(); using (MemoryStream ms = new MemoryStream()) { await downloadInfo.Content.CopyToAsync(ms); ms.Position = 0; // 解析Word文档内容 using (WordprocessingDocument doc = WordprocessingDocument.Open(ms, false)) { Body body = doc.MainDocumentPart.Document.Body; string textContent = body.InnerText; char[] separator = { ' ' }; string[] contentArray = textContent.Split(separator); // 调用表单更新逻辑 // reader.FillForm(contentArray); Console.WriteLine("解析后的字符串数组长度: {0}", contentArray.Length); } } Console.WriteLine("SAS {0} 读取处理成功", sasUri); } catch (RequestFailedException e) { if (e.Status == 403) { Console.WriteLine("SAS {0} 读取失败,权限不足", sasUri); Console.WriteLine("错误信息: " + e.Message); } else { Console.WriteLine(e.Message); throw; } } catch (Exception ex) { Console.WriteLine("文件处理失败: " + ex.Message); throw; } }
关键注意事项
- 权限配置:确保生成SAS的身份(Azure AD用户/服务主体)拥有存储账户的存储Blob数据参与者角色,或自定义包含
generateUserDelegationKey权限的角色。 - Word版本兼容:若处理旧版.doc文件,需使用Aspose.Words等支持二进制Word格式的库。
- SAS有效期:根据业务需求调整
ExpiresOn时间,避免过长有效期带来安全风险。 - 异常扩展:可增加Blob不存在、文件格式错误等场景的异常捕获,提升代码健壮性。
内容的提问来源于stack exchange,提问作者Jeanpaul
相关产品推荐
相关产品推荐

