401 通过 Azure APIM 发送请求调用 Cosmos DB Api 时未经授权

问题描述 投票:0回答:2

通过 APIM 频繁调用 CosmosDB API 时

send-request
有时我会收到 401 Unauthorized,有时会收到我期望的 200。我尝试生成相同的请求并使用 Postman 频繁发送它,并且响应始终为 200。

这是 APIM 策略代码片段:

    <set-variable name="currentDate" value="@(DateTime.UtcNow.ToString("r"))" />
    <set-variable name="userMetadataCosmosDBKey" value="{{UserMetadataCosmosDBKey}}" />
    <set-variable name="userMetadataCosmosDBUri" value="{{UserMetadataCosmosDBUri}}" />
    <set-variable name="userMetadataResourceId" value="{{UserMetadataResourceId}}" />
    <set-variable name="token" value="@{
      var verb = "POST";
      var resourceType = "docs";
      var resourceId = (string)context.Variables["userMetadataResourceId"];
      var date = (string)context.Variables["currentDate"];
      var key = (string)context.Variables["userMetadataCosmosDBKey"];
      var keyType = "master";
      var tokenVersion = "1.0";
      var hmacSha256 = new System.Security.Cryptography.HMACSHA256 { Key = Convert.FromBase64String(key) };                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
      verb = verb ?? "";
      resourceType = resourceType ?? "";
      resourceId = resourceId ?? "";
      string payLoad = string.Format("{0}\n{1}\n{2}\n{3}\n{4}\n",
      verb.ToLowerInvariant(),
      resourceType.ToLowerInvariant(),
      resourceId,
      date.ToLowerInvariant(),
      "");
      byte[] hashPayLoad = hmacSha256.ComputeHash(System.Text.Encoding.UTF8.GetBytes(payLoad));
      string signature = Convert.ToBase64String(hashPayLoad);
      return String.Format("type={0}&ver={1}&sig={2}",
        keyType,
        tokenVersion,
        signature);        
     }" />
    <send-request mode="new" response-variable-name="userMetadataResponse" timeout="20" ignore-error="false">
        <set-url>@(new Uri(string.Format("{0}{1}/docs",(string)context.Variables["userMetadataCosmosDBUri"],(string)context.Variables["userMetadataResourceId"])).ToString())</set-url>
        <set-method>POST</set-method>
        <set-header name="x-ms-documentdb-isquery" exists-action="override">
            <value>true</value>
        </set-header>
        <set-header name="Content-Type" exists-action="override">
            <value>application/query+json</value>
        </set-header>
        <set-header name="x-ms-version" exists-action="override">
            <value>2017-02-22</value>
        </set-header>
        <set-header name="x-ms-date" exists-action="override">
            <value>@((string)context.Variables["currentDate"])</value>
        </set-header>
        <set-header name="x-ms-query-enable-crosspartition" exists-action="override">
            <value>true</value>
        </set-header>
        <set-header name="Authorization" exists-action="override">
            <value>@((string)context.Variables["token"])</value>
        </set-header>
        <set-body>@{  
                        return new JObject(  
                            new JProperty("query","SELECT * FROM c WHERE c.APIMUserId=@apiUserId"),  
                            new JProperty("parameters", 
                                new JArray(
                                    new JObject(  
                                        new JProperty("name","@apiUserId"),  
                                        new JProperty("value", context.User.Id)
                                        )
                                    )
                                )
                            ).ToString();  
                    }</set-body>
    </send-request>
    <!-- Store response body in userMetadata variable -->
    <set-variable name="userMetadata" value="
      @{
         var response = ((IResponse)context.Variables["userMetadataResponse"]).Body.As<JObject>(true);                                                                                                                                                                                                           
         var metadata = response["_count"].ToString() == "1" ? response["Documents"][0] : new JObject();                                                                                                                                                                                                                                                
         return metadata;                                                                                                                                                                                                                                                
       }" />

有想过为什么我有时会收到 401 吗?

azure azure-cosmosdb policy azure-api-management
2个回答
3
投票

通过将

System.Uri.EscapeDataString()
添加到返回的令牌来使其工作:

System.Uri.EscapeDataString(String.Format("type={0}&ver={1}&sig={2}",
                                    keyType,
                                    tokenVersion,
                                    signature));

0
投票

您也可以使用

<authentication-managed-identity 
    resource="https://cosmon-samples-234f1f22a3.documents.azure.com" 
    output-token-variable-name="msi-access-token" 
    ignore-error="false" />

<set-header name="Authorization" exists-action="override">
    <value>@("type=aad&ver=1.0&sig=" + context.Variables["msi-access-token"])</value>
</set-header>

验证对 CosmosDB 的 APIM 请求。 只需确保您已在 CosmosDB RBAC 中授予权限 https://learn.microsoft.com/en-us/azure/cosmos-db/how-to-setup-rbac

包含所有详细信息的完整示例可以在我的文章中找到https://byalexblog.net/article/azure-apimanagement-to-azure-cosmosdb/

© www.soinside.com 2019 - 2024. All rights reserved.