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

时间:2018-01-25 06:49:25

标签: azure azure-cosmosdb policy azure-api-management

当经常通过APIM send-request频繁调用CosmosDB API时,我有时会获得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?

1 个答案:

答案 0 :(得分:1)

通过向返回的令牌添加System.Uri.EscapeDataString()来实现它:

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