Azure 资源管理 API。创建服务总线混合连接时的授权问题
Azure Resources Management API. Authorization issue when creating Service Bus Hybrid Connection
我们尝试使用 Azure 资源管理 API 创建混合连接。
(https://docs.microsoft.com/en-us/rest/api/relay/hybridconnections.)
我们遇到的问题是每次我们提交 HTTP 请求时 returns 我们 401 错误消息:
{
"error":{"code":"AuthenticationFailedInvalidHeader","message":"Authentication
failed. The 'Authorization' header is provided in an invalid
format."}}
我们更喜欢使用 REST API 而不是 SDK/nugget 包
这是控制台应用程序代码:
using System;
using System.Globalization;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Web;
namespace HybridConnectionManagement
{
class Program
{
public const string RelayAddress = "https://[namespace].servicebus.windows.net/";
private static string RelaySasKeyName = "RootManageSharedAccessKey";
private static string RelaySasKey = "[RootManageSharedAccessKey_Primary_Key]";
static void Main(string[] args)
{
var createHybridConnectionEndpoint = "https://management.azure.com" +
"/subscriptions/[subscription_id]" +
"/resourceGroups/[resourceGroup]" +
"/providers/Microsoft.Relay" +
"/namespaces/[namespace]" +
"/hybridConnections/test-521?api-version=2017-04-1";
var token = GetSASToken(RelayAddress, RelaySasKeyName, RelaySasKey);
using (var httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", token);
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json");
var response = httpClient.GetAsync(createHybridConnectionEndpoint).Result;
var responseText = response.Content.ReadAsStringAsync().Result;
//responseText is always:
//{ "error":{"code":"AuthenticationFailedInvalidHeader","message":"Authentication failed.
//The 'Authorization' header is provided in an invalid format."}}
Console.WriteLine(responseText);
}
}
public static string GetSASToken(string resourceUri, string keyName, string key)
{
var sinceEpoch = DateTime.UtcNow - new DateTime(1970, 1, 1);
var expiry = Convert.ToString((int)sinceEpoch.TotalSeconds + 3600); //EXPIRES in 1h
string stringToSign = HttpUtility.UrlEncode(resourceUri) + "\n" + expiry;
var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key));
var signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));
var sasToken = String.Format(CultureInfo.InvariantCulture,
"SharedAccessSignature sr={0}&sig={1}&se={2}&skn={3}",
HttpUtility.UrlEncode(resourceUri), HttpUtility.UrlEncode(signature), expiry, keyName);
return sasToken;
}
}
}
我对不同类型的身份验证感到困惑 API。
对于这种情况,我不必使用 SAS 令牌。我需要使用的是 Authorization Bearer 令牌。以下是获取它的方法:
private string AcquireToken()
{
var credentials = new UserPasswordCredential(UserName, Password);
var authenticationContext = new AuthenticationContext("https://login.windows.net/" + DirectoryName);
var result = authenticationContext.AcquireTokenAsync("https://management.core.windows.net/", AdClientId, credentials).GetAwaiter().GetResult();
return result.AccessToken;
}
因此,如果您将上面示例中的 GetSASToken 替换为此方法,则它可以工作。
我们尝试使用 Azure 资源管理 API 创建混合连接。 (https://docs.microsoft.com/en-us/rest/api/relay/hybridconnections.)
我们遇到的问题是每次我们提交 HTTP 请求时 returns 我们 401 错误消息:
{ "error":{"code":"AuthenticationFailedInvalidHeader","message":"Authentication failed. The 'Authorization' header is provided in an invalid format."}}
我们更喜欢使用 REST API 而不是 SDK/nugget 包
这是控制台应用程序代码:
using System;
using System.Globalization;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Web;
namespace HybridConnectionManagement
{
class Program
{
public const string RelayAddress = "https://[namespace].servicebus.windows.net/";
private static string RelaySasKeyName = "RootManageSharedAccessKey";
private static string RelaySasKey = "[RootManageSharedAccessKey_Primary_Key]";
static void Main(string[] args)
{
var createHybridConnectionEndpoint = "https://management.azure.com" +
"/subscriptions/[subscription_id]" +
"/resourceGroups/[resourceGroup]" +
"/providers/Microsoft.Relay" +
"/namespaces/[namespace]" +
"/hybridConnections/test-521?api-version=2017-04-1";
var token = GetSASToken(RelayAddress, RelaySasKeyName, RelaySasKey);
using (var httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", token);
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json");
var response = httpClient.GetAsync(createHybridConnectionEndpoint).Result;
var responseText = response.Content.ReadAsStringAsync().Result;
//responseText is always:
//{ "error":{"code":"AuthenticationFailedInvalidHeader","message":"Authentication failed.
//The 'Authorization' header is provided in an invalid format."}}
Console.WriteLine(responseText);
}
}
public static string GetSASToken(string resourceUri, string keyName, string key)
{
var sinceEpoch = DateTime.UtcNow - new DateTime(1970, 1, 1);
var expiry = Convert.ToString((int)sinceEpoch.TotalSeconds + 3600); //EXPIRES in 1h
string stringToSign = HttpUtility.UrlEncode(resourceUri) + "\n" + expiry;
var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key));
var signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));
var sasToken = String.Format(CultureInfo.InvariantCulture,
"SharedAccessSignature sr={0}&sig={1}&se={2}&skn={3}",
HttpUtility.UrlEncode(resourceUri), HttpUtility.UrlEncode(signature), expiry, keyName);
return sasToken;
}
}
}
我对不同类型的身份验证感到困惑 API。 对于这种情况,我不必使用 SAS 令牌。我需要使用的是 Authorization Bearer 令牌。以下是获取它的方法:
private string AcquireToken()
{
var credentials = new UserPasswordCredential(UserName, Password);
var authenticationContext = new AuthenticationContext("https://login.windows.net/" + DirectoryName);
var result = authenticationContext.AcquireTokenAsync("https://management.core.windows.net/", AdClientId, credentials).GetAwaiter().GetResult();
return result.AccessToken;
}
因此,如果您将上面示例中的 GetSASToken 替换为此方法,则它可以工作。