我有一些代码用于调用Azure Scheduler获取令牌,然后使用该令牌进行休息调用。是一种享受。
所以我决定将代码应用到一个新的应用程序中,但这次调用我自己的web api托管在azure上。 API在Active目录中注册我创建了一个密钥等。当我初始化我的静态httpclient时,它成功获取了一个令牌。
但是当我使用令牌进行身份验证调用API时,响应是401"未授权",下面是代码。
public static class SchedulerHttpClient
{
const string SPNPayload = "resource={0}&client_id={1}&grant_type=client_credentials&client_secret={2}";
private static Lazy<Task<HttpClient>> _Client = new Lazy<Task<HttpClient>>(async () =>
{
string baseAddress = ConfigurationManager.AppSettings["BaseAddress"];
var client = new HttpClient();
client.BaseAddress = new Uri(baseAddress);
await MainAsync(client).ConfigureAwait(false);
return client;
});
public static Task<HttpClient> ClientTask => _Client.Value;
private static async Task MainAsync(HttpClient client)
{
string tenantId = ConfigurationManager.AppSettings["AzureTenantId"];
string clientId = ConfigurationManager.AppSettings["AzureClientId"];
string clientSecret = ConfigurationManager.AppSettings["AzureClientSecret"];
string token = await AcquireTokenBySPN(client, tenantId, clientId, clientSecret).ConfigureAwait(false);
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token); //TODO ssmith: const or localization
}
private static async Task<string> AcquireTokenBySPN(HttpClient client, string tenantId, string clientId, string clientSecret)
{
var payload = String.Format(SPNPayload,
WebUtility.UrlEncode(ConfigurationManager.AppSettings["ARMResource"]),
WebUtility.UrlEncode(clientId),
WebUtility.UrlEncode(clientSecret));
var body = await HttpPost(client, tenantId, payload).ConfigureAwait(false);
return body.access_token;
}
private static async Task<dynamic> HttpPost(HttpClient client, string tenantId, string payload)
{
var address = String.Format(ConfigurationManager.AppSettings["TokenEndpoint"], tenantId);
var content = new StringContent(payload, Encoding.UTF8, "application/x-www-form-urlencoded");
using (var response = await client.PostAsync(address, content).ConfigureAwait(false))
{
if (!response.IsSuccessStatusCode)
{
Console.WriteLine("Status: {0}", response.StatusCode);
Console.WriteLine("Content: {0}", await response.Content.ReadAsStringAsync().ConfigureAwait(false));
}//TODO: start removing tests
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsAsync<dynamic>().ConfigureAwait(false);
}
}
}
上面的代码是创建httpclient并获得其授权的类。
public virtual async Task<T> GetAsync(string apiURL)
{
try
{
_client = await SchedulerHttpClient.ClientTask;
var response = await _client.GetAsync(apiURL);
response.EnsureSuccessStatusCode();
var responseContent = await response.Content.ReadAsAsync<T>().ConfigureAwait(false);
return responseContent;
}
catch (Exception e)
{
return default(T);
}
}
上面的代码是我的旧代码的快速提升,只是为了测试我是否可以获得任何结果。但正如所述,它返回401。
我的问题是,我的旧代码是不正确的授权?
<add key="ARMResource" value="https://management.core.windows.net/" />
<add key="TokenEndpoint" value="https://login.windows.net/{0}/oauth2/token" />
<add key="BaseAddress" value="https://mysite.azurewebsites.net" />
答案 0 :(得分:0)
如所怀疑的那样,这个特殊问题是由于在网络API的情况下错误的“ARMresource”导致我需要将其更改为客户端ID。
似乎我的问题是一样的,但我怀疑我可以完全从我的SPNPayload字符串中省略资源。