暂无图片
暂无图片
暂无图片
暂无图片
1
暂无图片

如何在 .NET 中获取 Azure REST API 的 Access Token

汪宇杰博客 2021-08-23
1342

点击上方蓝字 / 关注“汪宇杰博客”

导语

我最近在做一个需要前端调用 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


获取 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; }

}

测试 Access Token


复制 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

无广告,不卖课,做纯粹的技术公众号

文章转载自汪宇杰博客,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论

麦東
暂无图片
1年前
评论
暂无图片 0
可以给个demo吗?
1年前
暂无图片 点赞
评论