如何在 C# 中使用服务主体(clientId 和 clientSecret)为 Azure Data Lake Store(Gen-2)创建 SAS 令牌?

Posted

技术标签:

【中文标题】如何在 C# 中使用服务主体(clientId 和 clientSecret)为 Azure Data Lake Store(Gen-2)创建 SAS 令牌?【英文标题】:How to create SAS token for Azure Data Lake Store (Gen-2) using service principals (clientId and clientSecret) in C#? 【发布时间】:2020-06-30 12:00:06 【问题描述】:

我有 Data Lake Store (Gen-2) 的 clientId 和 clientSecret,我正在寻找一种使用 C# 以编程方式为其创建 SAS 令牌的方法。我浏览了文档,但没有找到创建 SAS 令牌的方法。任何指导将不胜感激。谢谢。

按照 Md Farid Uddin Kiron 的建议,我使用了这段代码但没有成功:

//Token Request End Point
string tokenUrl = $"https://login.microsoftonline.com/<tenantId>.onmicrosoft.com/oauth2/token";
var tokenRequest = new HttpRequestMessage(HttpMethod.Post, tokenUrl);

//I am Using client_credentials as It is mostly recommended
tokenRequest.Content = new FormUrlEncodedContent(new Dictionary<string, string>
            
                ["grant_type"] = "client_credentials",
                ["client_id"] = "--------",
                ["client_secret"] = "-------",
                ["resource"] = "https://<datalake gen2 name>.dfs.core.windows.net/"
            );

            dynamic json;
AccessTokenClass results = new AccessTokenClass();
HttpClient client = new HttpClient();

var tokenResponse = client.SendAsync(tokenRequest).GetAwaiter();

json = tokenResponse.GetResult().Content.ReadAsStringAsync().GetAwaiter();
results = JsonConvert.DeserializeObject<AccessTokenClass>(json);

它给了我状态 400 错误。

【问题讨论】:

请看这个answerfollow the token part。希望这会有所帮助。如果您仍有任何疑虑,请告诉我。 @MdFaridUddinKiron,感谢您的回复,但它不起作用。 能否请您分享您的问题或代码 sn-p 以便它可以重现。 @MdFaridUddinKiron,我已经更新了问题并添加了代码,它给了我 400 状态错误。 您的resource 似乎不正确。应该是https://datalake.azure.net/ 【参考方案1】:

如果要使用 Azure AD 访问令牌访问 Azure Data Lake gen2,请参考以下代码

    创建服务主体并为 sp 分配 Azure RABC 角色。
az login
az account set --subscription "<your subscription id>"
# it will assign Storage Blob Data Contributor to the sp at subscription level
az ad sp create-for-rbac -n "mysample" --role Storage Blob Data Contributor

    代码
string tokenUrl = $"https://login.microsoftonline.com/<tenantId>.onmicrosoft.com/oauth2/token";
var tokenRequest = new HttpRequestMessage(HttpMethod.Post, tokenUrl);

//I am Using client_credentials as It is mostly recommended
tokenRequest.Content = new FormUrlEncodedContent(new Dictionary<string, string>
            
                ["grant_type"] = "client_credentials",
                ["client_id"] = "--------",
                ["client_secret"] = "-------",
                ["resource"] = "https://storage.azure.com/"
            );

            dynamic json;
AccessTokenClass results = new AccessTokenClass();
HttpClient client = new HttpClient();

var tokenResponse = client.SendAsync(tokenRequest).GetAwaiter();

json = tokenResponse.GetResult().Content.ReadAsStringAsync().GetAwaiter();
results = JsonConvert.DeserializeObject<AccessTokenClass>(json);

如果要创建sas token,请参考以下步骤

    通过 Azure 门户获取帐户密钥

    代码

var key = account key you copy";
            var accountName = "testadls05";
            StorageSharedKeyCredential credential = new StorageSharedKeyCredential(accountName, key);
            AccountSasBuilder sas = new AccountSasBuilder
            
                Protocol = SasProtocol.None,
                Services = AccountSasServices.Blobs,
                ResourceTypes = AccountSasResourceTypes.All,
                StartsOn = DateTimeOffset.UtcNow.AddHours(-1),
                ExpiresOn = DateTimeOffset.UtcNow.AddHours(1),

            ;
            sas.SetPermissions(AccountSasPermissions.All);

            var uri = $"https://accountName.dfs.core.windows.net/";

            UriBuilder sasUri = new UriBuilder(uri);
            sasUri.Query = sas.ToSasQueryParameters(credential).ToString();

            DataLakeServiceClient service = new DataLakeServiceClient(sasUri.Uri);
            var result =service.GetFileSystems().First();
            Console.WriteLine(result.Name);

【讨论】:

感谢您的帮助,但我想使用非密钥的服务主体生成 Data Lake Gen-2 的 SAS。在您的最新代码中,您使用帐户密钥生成 SAS。 @BilalShafqat 我们无法使用服务主体来创建 sas 令牌:docs.microsoft.com/en-us/rest/api/storageservices/… @BilalShafqatb 您还有其他顾虑吗?【参考方案2】:

以下代码可用于使用服务原则为 datalake gen2 创建 SAS 令牌:

这里密码是Client Secret,用户名是ClientId

$securePassword = ConvertTo-SecureString -AsPlainText -Force -String $Password
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $UserName, $securePassword
Connect-AzAccount -Credential $Credential -ServicePrincipal -Tenant $Tenant -Subscription $SubscriptionName

Write-Host -ForegroundColor Green "Creating an account level SAS Token.."
## Get the storage account
$storageAcc=Get-AzStorageAccount -ResourceGroupName $resourceGroupName -Name $storageAccName
## Get the storage account context
$ctx=$storageAcc.Context
## Creates an account-level SAS token.
New-AzStorageAccountSASToken -Context $ctx -Service Blob,File,Table,Queue -ResourceType Service,Container,Object -Permission "racwdlup" -StartTime "2020-06-18" -ExpiryTime "2022-06-18"

【讨论】:

以上是关于如何在 C# 中使用服务主体(clientId 和 clientSecret)为 Azure Data Lake Store(Gen-2)创建 SAS 令牌?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 MQTT 中使用特定类型的 clientId 创建客户端?

在 C# 中,如何使用反射计算表达式主体输出函数中包含的属性数量?

如何根据 clientid 和客户端密码在 Runbook 中运行 powershell 脚本

App Engine 和 Google 游戏服务 clientId 冲突

Spring Oauth2:如何获取所有clientIds?

如何在 POST 中发送 ClientId 和 ClientSecret,而不是在带有 ClientCredentialsAccessTokenProvider 的标头中发送