这是我的代码,用于查找存储容器:
var api = $"https://{storageAccountName}.blob.core.windows.net/?comp=list";
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken); //token obtained from https://storage.azure.com/
client.BaseAddress = new Uri($"https://{storageAccountName}.blob.core.windows.net/");
using (var responseGet = client.GetAsync(api).Result)
{
if (responseGet.IsSuccessStatusCode)
{
var xmlDocument = new XmlDocument();
xmlDocument.LoadXml(responseGet.Content.ReadAsStringAsync().Result);
foreach (XmlNode a in xmlDocument.DocumentElement.SelectNodes("Containers/Container"))
{
containerNameList.Add(a.SelectSingleNode("Name").FirstChild.Value);
}
}
}
}
我有一个错误:
`StatusCode:403,ReasonPhrase:“服务器无法通过身份验证请求。确保形成了Authorization标头的值正确地包含签名。”,版本:1.1,内容:
System.Net.Http.HttpConnection+HttpConnectionResponseContent, Headers:
{
Server: Windows-Azure-Blob/1.0
Server: Microsoft-HTTPAPI/2.0
x-ms-request-id: 9d70d7ff-901e-0096-4c5b-aec38d000000
Date: Mon, 09 Dec 2019 06:38:16 GMT
Content-Length: 438
Content-Type: application/xml
}`
我从https://storage.azure.com/
获得了访问令牌
这是删除存储容器的代码:
var strApi = $"https://{storageAccountName}.blob.core.windows.net/{storageContainerName}?restype=container";
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);
client.BaseAddress = new Uri(BaseManagementUri);
using (var responseGet = client.DeleteAsync(strApi).Result)
{
if (responseGet.IsSuccessStatusCode)
{
log.LogInformation($"Deleted {storageAccountName}");
}
else
{
log.LogWarning($"Failed to deleted {storageAccountName}\n{responseGet.Content.ReadAsByteArrayAsync().Result}");
}
}
}
如何获得正确的访问令牌以及上述操作所需的所有标头是什么?
根据我的研究,我们可以使用Azure Active Directory(AD)授权对Blob存储的请求。有关更多详细信息,请参阅document
详细步骤如下。
Storage Blob Data Contributor
角色分配给sp。您可以参考article以了解更多有关如何操作的详细信息。 az ad sp create-for-rbac --name "" --scope <"/subscriptions/<subscription>/resourceGroups/<resource-group>/providers/Microsoft.Storage/storageAccounts/<storage-account>"> --role "Storage Blob Data Contributor"
URL : https://login.microsoftonline.com/{tenant}/v2.0/token
Method : POST
Headers : Content-Type: application/x-www-form-urlencoded
Body :
"grant_type" : "client_credentials"
"scope" : "https://storage.azure.com/.default"
"client_id" : "<your sp app id>"
"client_secret" : "<your sp password>"
URL: https://myaccount.blob.core.windows.net/?comp=list
Method: Get
Headers:
x-ms-version : 2019-02-02
Authorization: Bearer <access token>
URL: https://myaccount.blob.core.windows.net/mycontainer?restype=container
Method : DELETE
Headers:
x-ms-version : 2019-02-02
Authorization: Bearer <access token>
此外,如果要使用Azure MSI进行此操作,请参考blog
更新
关于如何在Azure函数中使用MSI调用Azure存储休息api,请参考以下步骤。1. Adding a system-assigned identity
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System.Xml.Linq;
using Microsoft.Azure.Services.AppAuthentication;
using RestSharp;
using System.Text;
namespace TestFunV2
{
public static class Function1
{
[FunctionName("Function1")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
var tokenProvider = new AzureServiceTokenProvider();
var accesstoken = await tokenProvider.GetAccessTokenAsync("https://storage.azure.com/");
var client = new RestClient("https://hurystorage.blob.core.windows.net/?comp=list");
var request = new RestRequest(Method.GET);
request.AddHeader("Authorization", "Bearer " + accesstoken);
request.AddHeader("x-ms-version", "2019-02-02");
IRestResponse response = await client.ExecuteTaskAsync(request);
if (response.IsSuccessful) {
var xmlstring = response.Content;
string _byteOrderMarkUtf8 = Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble());
if (xmlstring.StartsWith(_byteOrderMarkUtf8))
{
xmlstring = xmlstring.Remove(0, _byteOrderMarkUtf8.Length);
}
XElement x = XElement.Parse(xmlstring);
foreach (XElement container in x.Element("Containers").Elements("Container"))
{
log.LogInformation("Container name = {0}", container.Element("Name").Value);
}
return (ActionResult)new OkObjectResult("ok");
}
return new BadRequestObjectResult("failure");
}
}
}