
点击上方蓝字 / 关注“汪宇杰博客”
导语
我最近在做一个需要前端调用 Azure REST API 的项目。微软文档描述了如何通过 Jon Gallant 的博客文章在 postman 中获取 Access Token。但是,将密钥放在前端是非常危险的。在我的项目中,我必须从 .NET 的服务器端获取 Access Token。让我们一起看一下吧。
微软文档:https://docs.microsoft.com/en-us/rest/api/azure?WT.mc_id=AZ-MVP-5002809
博客文章:https://blog.jongallant.com/2021/02/azure-rest-apis-postman-2021/
为了获取用于调用 Azure REST API 的 Access Token,你必须首先按照微软文档中的说明在 Azure AD 中注册一个应用程序。如果觉得微软文档又臭又长,你只需按照以下步骤快速搞定。
打开你的 Azure AD, App registrations, 点击 "New registration"
为其命名,然后单击“Register”以完成应用程序注册。
打开 "Certificates & secrets", 点击 "New client secret"
就我而言,我添加了一个将在 24 个月后过期的密钥。
复制 Value 并保存以备后用。这个值只会显示一次,所以一定要把它复制出来。
打开需要 REST API 访问权限的资源的 IAM。在我的案例里是一个资源组。
将刚才注册的应用程序添加到资源组并为其分配所需的角色,在我的案例里为“Contributor”。
获取 Access Token 的方法有很多种。在官方postman示例中,预请求脚本将发送 POST 请求并获取访问令牌。
您需要一个client id、一个tenant id 和一个我们在上一节中复制的客户端密钥来获取 Access Token。另外两个可以从您之前注册的应用程序中复制。
pm.sendRequest({
url: 'https://login.microsoftonline.com/' + pm.collectionVariables.get("tenantId") + '/oauth2/token',
method: 'POST',
header: 'Content-Type: application/x-www-form-urlencoded',
body: {
mode: 'urlencoded',
urlencoded: [
{ key: "grant_type", value: "client_credentials", disabled: false },
{ key: "client_id", value: pm.collectionVariables.get("clientId"), disabled: false },
{ key: "client_secret", value: pm.collectionVariables.get("clientSecret"), disabled: false },
{ key: "resource", value: pm.collectionVariables.get("resource") || "https://management.azure.com/", disabled: false }
]
}
}, function (err, res) {
if (err) {
console.log(err);
} else {
let resJson = res.json();
pm.collectionVariables.set("bearerTokenExpiresOn", resJson.expires_on);
pm.collectionVariables.set("bearerToken", resJson.access_token);
}
});
在 .NET 中,根据微软的说法,你可以使用 Azure SDK for .NET 库来实现。但在我的情况下,我的后端代码中唯一的事情就是将访问令牌返回给前端,我不想使用繁重的库只是为了使用它的 1% 的功能。所以我决定使用 .NET 内置的 HttpClient 来做这件事。
代码很简单,就是把上述 postman 脚本的用 C# 自主研发成功。
var tenantId = "<your tenant id>";
var clientId = "<your client id>";
var secret = "<your secret>";
var resourceUrl = "https://management.azure.com/";
var requestUrl = $"https://login.microsoftonline.com/{tenantId}/oauth2/token";
// in real world application, please use Typed HttpClient from ASP.NET Core DI
var httpClient = new HttpClient();
var dict = new Dictionary<string, string>
{
{ "grant_type", "client_credentials" },
{ "client_id", clientId },
{ "client_secret", secret },
{ "resource", resourceUrl }
};
var requestBody = new FormUrlEncodedContent(dict);
var response = await httpClient.PostAsync(requestUrl, requestBody);
response.EnsureSuccessStatusCode();
var responseContent = await response.Content.ReadAsStringAsync();
var aadToken = JsonSerializer.Deserialize<AzureADToken>(responseContent);
Console.WriteLine(aadToken?.AccessToken);
AzureADToken 类型
public class AzureADToken
{
[JsonPropertyName("token_type")]
public string TokenType { get; set; }
[JsonPropertyName("expires_in")]
public string ExpiresIn { get; set; }
[JsonPropertyName("ext_expires_in")]
public string ExtExpiresIn { get; set;
[JsonPropertyName("expires_on")]
public string ExpiresOn { get; set; }
[JsonPropertyName("not_before")]
public string NotBefore { get; set; }
public string Resource { get; set; }
[JsonPropertyName("access_token")]
public string AccessToken { get; set; }
}
复制 token 并打开 postman。尝试 HTTP GET 请求。
https://management.azure.com/subscriptions/<your subscription id>/resourcegroups?api-version=2020-09-01
token 验证成功,并且 Azure REST API 也工作正常!
为了让 HttpClient 在 ASP.NET Core 应用里不那么容易爆,推荐阅读 Use IHttpClientFactory to implement resilient HTTP requests 文档。
https://docs.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests?WT.mc_id=AZ-MVP-5002809

汪宇杰博客
Azure | .NET | 微软 MVP
无广告,不卖课,做纯粹的技术公众号
评论
