【Azure Storage Account】利用App Service作为反向代理, 并使用.NET Storage Account SDK实现上传/下载操作

news/2025/3/1 22:00:43/文章来源:https://www.cnblogs.com/lulight/p/18745481

问题描述

在使用Azure上的存储服务 Storage Account 的时候,有时需要代替 它原本提供的域名进行访问,比如默认的域名为:mystorageaccount.blob.core.chinacloudapi.cn, 想转变为 myservice.file.com

如果使用App Service作为反向代理,我们现在有如下三个疑问:

第一:如何来设置方向代理呢?

第二:是否还能成功访问Storage Account服务呢? 

第三:.NET Storage Account SDK中如何使用自定义的域名连接服务呢?

 

问题解答

根据问题中的三个疑问,我们一一测试及解答。

第一问,在App Service服务中如何实现反向代理呢?

参考之前的文章:

  1. 【Azure 应用服务】在App Service for Windows中实现反向代理 : https://www.cnblogs.com/lulight/p/17120713.html
  2. 【应用服务 App Service】 App Service Rewrite 实例 - 反向代理转发功能 : https://www.cnblogs.com/lulight/p/13875393.html

第一步:applicationhost.xdt 启用IIS代理功能

选择一个 Windows 平台的App Service,进入Kudu站点,在 Site 目录下创建 applicationhost.xdt 文件并复制下面的内容

<?xml version="1.0"?><configuration xmlns:xdt=http://schemas.microsoft.com/XML-Document-Transform><system.webServer><proxy xdt:Transform="InsertIfMissing" enabled="true" preserveHostHeader="false" reverseRewriteHostInResponseHeaders="false" /></system.webServer>
</configuration>
  • xdt:Transform="InsertIfMissing" 表示如果代理配置不存在,则插入这一配置。
  • enabled="true" 表示启用代理功能。
  • preserveHostHeader="false" 表示不保留原始请求的主机头信息。
  • reverseRewriteHostInResponseHeaders="false" 表示在响应头中不反向重写主机头信息。

第二步:web.config 配置 rewrite rule

第一步完成后,点击 WWWROOT 目录,添加新文件 web.config 并复制下面的内容

<configuration>  <system.webServer>  <rewrite>  <rules>  <rule name="root" stopProcessing="true">  <match url="^/?(.*)" />  <action type="Rewrite" url="https://<stroage account name>.blob.core.chinacloudapi.cn/{R:1}" />  </rule>  <!-- 需要对根目录的请求进行反向代理,否则对POST/PUT等操作会报错404无法找到Blob Containers --><!-- <rule name="sa" stopProcessing="true">   --><!-- <match url="^sa/?(.*)" />   --><!-- <action type="Rewrite" url="https://<storage account name>.blob.core.chinacloudapi.cn/{R:1}" />   --><!-- </rule>   --></rules>  </rewrite>  </system.webServer>  
</configuration>


第二问,是否还能成功访问Storage Account服务呢? 

完成App Service的反向代理配置后,重启服务。然后进入Storage Account的共享访问签名生成页面。

 

第一步:使用原生的 SAS URL访问Blob文件

原生的URL为:

https://< your storage account >.blob.core.chinacloudapi.cn/<your container name>/<filename>.txt?

sp=r&st=2025-03-01T13:16:47Z&se=2025-03-01T21:16:47Z&spr=https&sv=2022-11-02&sr=b&sig=xxxx%xxxx%3D

第二步:用App Service的域名替换原生的Storage Account域名访问

替换后的URL为:

https://<your app service custom domain name>.chinacloudsites.cn/<your container name>/<filename>.txt?

sp=r&st=2025-03-01T13:16:47Z&se=2025-03-01T21:16:47Z&spr=https&sv=2022-11-02&sr=b&sig=xxxx%xxxx%3D

测试验证,两种域名均可访问。证明,反向代理配置成功!

 

 

第三问:.NET Storage Account SDK中如何使用自定义的域名连接服务呢?

是的,在默认的.NET Storage Account SDK中,默认使用的是连接字符串(Connection String)。

DefaultEndpointsProtocol=https;AccountName=storagesample;AccountKey=<account-key>;EndpointSuffix=core.chinacloudapi.cn

以上的格式,无法修改EndpointSuffix为自定义的域名。所以,使用连接字符串肯定是不可以的。

代替的方案就是使用共享访问签名(SAS URL)来初始化BlobServiceClient对象。

参考“快速入门:适用于 .NET 的 Azure Blob 存储客户端库” 文章中的代码,只需要修改初始化 Blob Service Client对象的那一段代码就可以,改动量非常小。

//Use SAS URL        
string accountsas = "https://<the app gateway domain name>/?sv=2022-11-02&ss=bfqt&srt=sco&sp=rwdlacupitfx&se=2025-02-28T13:55:27Z&st=2025-02-28T05:55:27Z&spr=https&sig=PxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxD";Uri sasuri = new Uri(accountsas);
// Create a BlobServiceClient object which will be used to create a container client
BlobServiceClient blobServiceClient = new BlobServiceClient(sasuri);

注意:代码中使用的共享访问签名SAS URL是Storage Account级别的,不能使用第二问中的一个blob文件的SAS URL,否则会出现权限不够报错。

运行效果展示:

 

 

参考资料

  1. 在App Service for Windows中实现反向代理 : https://www.cnblogs.com/lulight/p/17120713.html
  2. App Service Rewrite 实例 - 反向代理转发功能 : https://www.cnblogs.com/lulight/p/13875393.html
  3. BlobServiceClient 构造函数 : https://learn.microsoft.com/zh-cn/dotnet/api/azure.storage.blobs.blobserviceclient.-ctor?view=azure-dotnet#azure-storage-blobs-blobserviceclient-ctor(system-uri-azure-storage-storagesharedkeycredential-azure-storage-blobs-blobclientoptions)
  4. 快速入门:适用于 .NET 的 Azure Blob 存储客户端库 : https://docs.azure.cn/zh-cn/storage/blobs/storage-quickstart-blobs-dotnet?tabs=visual-studio%2Cconnection-string%2Croles-azure-portal%2Csign-in-azure-cli%2Cidentity-visual-studio

 

附录:如果在设置反向代理的时候,没有从根目录跳转,就会遇见如下错误:

The specified container does not exist.
RequestId:000000
Time:2025-02-28T05:57:16.7457335Z
Status: 404 (The specified container does not exist.)
ErrorCode: ContainerNotFound

Content:
<?xml version="1.0" encoding="utf-8"?><Error><Code>ContainerNotFound</Code><Message>The specified container does not exist. RequestId:00000 Time:2025-02-28T05:57:16.7457335Z</Message></Error>

Headers:
Date: Fri, 28 Feb 2025 05:57:16 GMT
Server: Windows-Azure-Blob/1.0,Microsoft-HTTPAPI/2.0
Set-Cookie: REDACTED
x-ms-request-id: e000000
x-ms-client-request-id: 5e
x-ms-version: 2020-08-04
x-ms-error-code: ContainerNotFound
X-Powered-By: REDACTED
Content-Length: 225
Content-Type: application/xml

附录:完整代码参考

using Azure;
using Azure.Identity;
using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models;
using System;
using System.IO;
using System.Text;
using System.Threading.Tasks;namespace BlobQuickstartV12
{class Program{static async Task Main(string[] args){Console.WriteLine("Hello World!");Console.WriteLine("Azure Blob storage v12 - .NET quickstart sample\n");// Retrieve the connection string for use with the application. The storage// connection string is stored in an environment variable on the machine// running the application called AZURE_STORAGE_CONNECTION_STRING. If the// environment variable is created after the application is launched in a// console or with Visual Studio, the shell or application needs to be closed// and reloaded to take the environment variable into account.//string connectionString = "Connection String";string accountsas = " SAS URL ";Uri sasuri = new Uri(accountsas);// Create a BlobServiceClient object which will be used to create a container clientBlobServiceClient blobServiceClient = new BlobServiceClient(sasuri);//Create a unique name for the containerstring containerName = "lbllmpackage";// "quickstartblobs" + Guid.NewGuid().ToString();// Create the container and return a container client objectBlobContainerClient containerClient = blobServiceClient.GetBlobContainerClient(containerName);Console.WriteLine("Listing blobs...");// List all blobs in the containerawait foreach (BlobItem blobItem in containerClient.GetBlobsAsync()){try{Console.WriteLine("\t" + blobItem.Name);BlobClient bclient = containerClient.GetBlobClient(blobItem.Name);await bclient.CreateSnapshotAsync();}catch (Exception ex){Console.WriteLine(ex.Message);}}var prp = containerClient.GetProperties();// Create a local file in the ./data/ directory for uploading and downloadingstring localPath = @".\data\";string fileName = "quickstart" + Guid.NewGuid().ToString() + ".txt";string localFilePath = Path.Combine(localPath, fileName);// Write text to the fileawait File.WriteAllTextAsync(localFilePath, "Hello, World! the message from .net");// Get a reference to a blobBlobClient blobClient = containerClient.GetBlobClient("/test/" + fileName);Console.WriteLine("Uploading to Blob storage as blob:\n\t {0}\n", blobClient.Uri);// Open the file and upload its datausing FileStream uploadFileStream = File.OpenRead(localFilePath);await blobClient.UploadAsync(uploadFileStream, true);uploadFileStream.Close();Console.WriteLine("Listing blobs...");// List all blobs in the containerawait foreach (BlobItem blobItem in containerClient.GetBlobsAsync()){Console.WriteLine("\t" + blobItem.Name);}// Download the blob to a local file// Append the string "DOWNLOADED" before the .txt extension // so you can compare the files in the data directorystring downloadFilePath = localFilePath.Replace(".txt", "DOWNLOADED.txt");Console.WriteLine("\nDownloading blob to\n\t{0}\n", downloadFilePath);// Download the blob's contents and save it to a fileBlobDownloadInfo download = await blobClient.DownloadAsync();using (FileStream downloadFileStream = File.OpenWrite(downloadFilePath)){await download.Content.CopyToAsync(downloadFileStream);downloadFileStream.Close();}}}
}

 

 

 

[END]

 

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大胆点!你猜DeepSeek的利润率有多高?

这种一周真是热闹啊,DeepSeek开源周,连续五天(2025年2月24日至28日)开源了5个核心技术项目,覆盖AI模型训练、推理优化、文件系统等多个领域,在今天还放出来了One more thing,直接把自己的利润率放出来了(真不拿用户当外人,哈哈) 接下来让我们一起来看看开源周都带来了…

通过网盘分享的文件:Oracle Database 12c linux版本 安装包

https://pan.baidu.com/s/14n1el1C0v1kbaHpDkw9i6w?pwd=1234 提取码: 1234

CountDownLatch的countDown()方法的底层源码

一、CountDownLatch的构造方法// 创建倒数闩,设置倒数的总数State的值CountDownLatch doneSignal = new CountDownLatch(N);二、countDown() 方法的作用 countDown() 方法的主要作用是将 CountDownLatch 的内部计数器减一。如果计数器减到零,则会唤醒所有等待的线程 三、coun…

论文+1

1.2 研究目标本研究旨在解决微服务架构中质量属性冲突和评估方法缺失的问题。具体目标如下:构建可量化的质量属性评估指标体系:通过深入分析微服务架构的特点和业务需求,明确性能、可用性、安全性等关键质量属性的量化指标,为后续的评估和优化提供准确的数据支持。 设计基于…

2.28 AI课堂训练测试

老师要求我们用指令训练Ai完成我们开学测试的代码,锻炼我们的业务逻辑 开学测试要求:请设计一个仓储管理系统原型系统,该系统支持多个仓库的设立。统一设立物资台账,物资台账需包含物资编码、物资名称、规格、材质、供应商、品牌、物资分类,用户可以自定义物资的物资分类。…

Obsidian + DeepSeek:免费 AI 助力你的知识管理,让你的笔记飞起来!

Obsidian + DeepSeek:免费 AI 助力你的知识管理,让你的笔记飞起来! 1. 优势介绍 Obsidian 是一款强大的本地知识管理软件,它像一个积木盒,让你用 Markdown 笔记搭建自己的知识宇宙。通过 双链笔记,你可以将不同的想法、灵感和信息连接起来,构建一个属于你自己的知识网络…

idea创建Spark项目报错记录

报错1:SparkException: A master URL must be set in your configuration解决方案:添加conf.setMaster("local"); local[“*”]中代表的是有几个线程,如果只写local就是单线程,如果是local[2]就是两个线程package com.fyq.spark.rdd;import org.apache.spark.Sp…

14.4.2 训练

首先来看看二元交叉熵的损失公式然后再来看看nn.functional.binary_cross_entropy_with_logits的用法然后来讲一下\(0.9352\)是怎么得出的(\(1.8462\)同理)每个样本没有归一化的输出为[1.1, -2.2, 3.3, -4.4],标签分别为[1.0, 0.0, 0.0, 0.0] 将这四个样本代入最开始给的二元…

【Nacos】源码以及启动环境搭建

1 前言 Nacos 现在越来越成为微服务结构中不可或缺的一部分,他的集成服务以及配置的管理一体化、简单方便也是我们手首选的原因,那么了解他的原理就很重要。所以我们这节拉取下源码调试下环境,方便我们观察服务注册的整体过程,以及配置下发等核心逻辑的过程,有助于更好的…