Rest 如何在C中使用SAS访问Azure blob#
当我尝试使用特别共享访问签名(SAS)创建/访问Azure blob时,我收到“远程服务器返回错误:(403)禁止”。错误。有人能帮我确定一下这个代码出了什么问题吗Rest 如何在C中使用SAS访问Azure blob#,rest,azure,blob,Rest,Azure,Blob,当我尝试使用特别共享访问签名(SAS)创建/访问Azure blob时,我收到“远程服务器返回错误:(403)禁止”。错误。有人能帮我确定一下这个代码出了什么问题吗 // Calling this function from Main(). public void uploadToBlob() { string content = "Hello World - Content of the file"; string fileName =
// Calling this function from Main().
public void uploadToBlob()
{
string content = "Hello World - Content of the file";
string fileName = "TestFile";
UploadFileToAzureBlobStorage(content, fileName);
}
void UploadFileToAzureBlobStorage(string content, string fileName)
{
string storageKey = "SAS Key";
string storageAccount = "Storage Account name";
string containerName = "Container Name";
string blobName = fileName;
string method = "PUT";
string sampleContent = content;
int contentLength = Encoding.UTF8.GetByteCount(sampleContent);
string requestUri = $"https://{storageAccount}.blob.core.windows.net/{containerName}/{blobName}";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUri);
string now = DateTime.UtcNow.ToString("R");
request.Method = method;
request.ContentType = "text/plain; charset=UTF-8";
request.ContentLength = contentLength;
request.Headers.Add("x-ms-version", "2015-12-11");
request.Headers.Add("x-ms-date", now);
request.Headers.Add("x-ms-blob-type", "BlockBlob");
request.Headers.Add("Authorization", AuthorizationHeader(method, now, request, storageAccount, storageKey, containerName, blobName));
using (Stream requestStream = request.GetRequestStream())
{
requestStream.Write(Encoding.UTF8.GetBytes(sampleContent), 0, contentLength);
}
using (HttpWebResponse resp = (HttpWebResponse)request.GetResponse())
{
if (resp.StatusCode == HttpStatusCode.OK)
{ }
}
}
public string AuthorizationHeader(string method, string now, HttpWebRequest request, string storageAccount, string storageKey, string containerName, string blobName)
{
string headerResource = $"x-ms-blob-type:BlockBlob\nx-ms-date:{now}\nx-ms-version:2015-12-11";
string urlResource = $"/{storageAccount}/{containerName}/{blobName}";
string stringToSign = $"{method}\n\n\n{request.ContentLength}\n\n{request.ContentType}\n\n\n\n\n\n\n{headerResource}\n{urlResource}";
HMACSHA256 hmac = new HMACSHA256(Encoding.ASCII.GetBytes(storageKey));
string signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));
String AuthorizationHeader = String.Format("{0} {1}:{2}", "SharedKey", storageAccount, signature);
return AuthorizationHeader;
}
当您使用帐户密钥时,需要上面使用的代码。此时,您需要在请求中计算并包括
授权
头。如果您使用的是共享访问签名(SAS)
令牌,则不需要执行所有这些操作,因为SAS令牌已经包含授权信息
假设您的SAS令牌是有效的,并且包含上载文件的适当权限,那么您的代码将变得非常简单。请参阅下面的修改代码:
void UploadFileToAzureBlobStorage(string content, string fileName)
{
string sasToken = "SAS Key";
string storageAccount = "Storage Account name";
string containerName = "Container Name";
string blobName = fileName;
string method = "PUT";
string sampleContent = content;
int contentLength = Encoding.UTF8.GetByteCount(sampleContent);
string requestUri = $"https://{storageAccount}.blob.core.windows.net/{containerName}/{blobName}?{sasToken}";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUri);
request.Method = method;
request.ContentType = "text/plain; charset=UTF-8";
request.ContentLength = contentLength;
request.Headers.Add("x-ms-blob-type", "BlockBlob");
using (Stream requestStream = request.GetRequestStream())
{
requestStream.Write(Encoding.UTF8.GetBytes(sampleContent), 0, contentLength);
}
using (HttpWebResponse resp = (HttpWebResponse)request.GetResponse())
{
if (resp.StatusCode == HttpStatusCode.OK)
{ }
}
}
我不知道这是否会直接起作用,因为我更改了connectionstring之外的一些内容。但也许会有帮助 请注意,在本例中,我将返回定义了头的映像路径,因为不需要将映像下载到服务器,最好直接交付到客户端
public static string ChaveStringConexao { get; set; }
public static string ObterUrlTemporaria(string container, string nomeBlob, string nomeOriginal, bool paraDownload = false)
{
var blob = InstanciaContainer(container).GetBlockBlobReference(nomeBlob);
var sasToken = string.Empty;
var sasPolicy = new SharedAccessBlobPolicy
{
Permissions = SharedAccessBlobPermissions.Read,
SharedAccessStartTime = DateTime.UtcNow.AddMinutes(-15),
SharedAccessExpiryTime = DateTime.UtcNow.AddMinutes(30)
};
var _sasHeader = new SharedAccessBlobHeaders
{
ContentDisposition = $"attachment; filename={nomeOriginal}"
};
if (paraDownload)
{
sasToken = blob.GetSharedAccessSignature(sasPolicy, _sasHeader);
}
else
{
sasToken = blob.GetSharedAccessSignature(sasPolicy);
}
return new Uri(blob.Uri, sasToken).AbsoluteUri;
}
public static CloudBlobContainer InstanciaContainer(string container)
{
var storageAccount = CloudStorageAccount.Parse(ChaveStringConexao);
var blobClient = storageAccount.CreateCloudBlobClient();
var blobContainer = blobClient.GetContainerReference(container);
return blobContainer;
}
网络配置的连接字符串示例:
<add name="AzureArmazenamento" connectionString="DefaultEndpointsProtocol=https;AccountName=*****;AccountKey=ZO78t1NKuiW32kKTBlm6bWRohREzYpmokpuFI4N**********************;EndpointSuffix=core.windows.net" />
var cnn = ConfigurationManager.ConnectionStrings["AzureArmazenamento"].ConnectionString;
AzureUtilitario.ChaveStringConexao = cnn;
var url = AzureUtilitario.ObterUrlTemporaria(container, file.key, file.OriginalName, download);
public static bool Salvar(string container, string nomeBlob, byte[] arquivo)
{
var blockBlob = InstanciaContainer(container).GetBlockBlobReference(nomeBlob);
blockBlob.Properties.ContentType = Path.GetExtension(nomeBlob).ConverteParaContentType();
using (var stream = new MemoryStream(arquivo))
{
blockBlob.UploadFromStream(stream);
return true;
}
}
对于上传,您不需要任何不同。SAS问题在返回文件时向您说明:
<add name="AzureArmazenamento" connectionString="DefaultEndpointsProtocol=https;AccountName=*****;AccountKey=ZO78t1NKuiW32kKTBlm6bWRohREzYpmokpuFI4N**********************;EndpointSuffix=core.windows.net" />
var cnn = ConfigurationManager.ConnectionStrings["AzureArmazenamento"].ConnectionString;
AzureUtilitario.ChaveStringConexao = cnn;
var url = AzureUtilitario.ObterUrlTemporaria(container, file.key, file.OriginalName, download);
public static bool Salvar(string container, string nomeBlob, byte[] arquivo)
{
var blockBlob = InstanciaContainer(container).GetBlockBlobReference(nomeBlob);
blockBlob.Properties.ContentType = Path.GetExtension(nomeBlob).ConverteParaContentType();
using (var stream = new MemoryStream(arquivo))
{
blockBlob.UploadFromStream(stream);
return true;
}
}
对于存储密钥,您使用的是帐户密钥还是SAS令牌?另外,您有响应头吗?@Guaurav Mantri,我在这里传递SAS令牌。@Cam Soper,下面是响应:AuthenticationFailedServer无法验证请求。确保包括签名在内的授权标头的值格式正确。RequestId:d4af7fcf-001e-0041-7532-4127e3000000时间:2017-10-09T19:10:06.7310979ZRequest日期标题太旧:“2017年10月9日星期一17:40:52 GMT”它工作起来很有魅力,感谢Gaurav的建议!!感谢您的输入Leandro,您的示例还为我提供了一些如何使代码正常工作的想法。