2017-08-02 96 views
4

我试图使用Cosmos DB REST Api部署cosmos数据库。我正在使用一个函数来构建授权头,我从https://gallery.technet.microsoft.com/scriptcenter/How-to-query-Azure-Cosmos-0a9aa517链接中获得了脚本。它工作得很好GET & POST但是当我试图执行一个PUT命令时,我总是得到错误。使用Powershell调用Rest API - CosmosDb

Invoke-RestMethod : The remote server returned an error: (401) Unauthorized.

我试图更新宇宙收集的报价,但它总是以错误结束,我不明白是什么原因。我还检查了我的标题和微软文档的授权,看起来很好。请参阅https://docs.microsoft.com/en-us/rest/api/documentdb/replace-an-offer以获取Uri和标题。我的请求和响应都低于

请求

PUT https: //mycosmosdb.documents.azure.com:443/offers/mycollection HTTP/1.1 
authorization: type % 3dmaster % 26ver % 3d1.0 % 26sig % 3dIgWkszNS % 2b94fUEyrG8frByB2PWSc1ZEszc06GUeuW7s % 3d 
x - ms - version: 2017 - 02 - 22 
x - ms - date: Wed, 02 Aug 2017 08: 40: 37 GMT 
User - Agent: Mozilla/5.0(Windows NT; Windows NT 10.0; en - US)WindowsPowerShell/5.1.15063.483 
Content - Type: application/json 
Host: mycosmosdb.documents.azure.com 
Content - Length: 269 
{ 
    "offerVersion": "V2", 
    "offerType": "Invalid", 
    "content": { 
     "offerThroughput": 500, 
     "offerIsRUPerMinuteThroughputEnabled": false 
    }, 
    "resource": "dbs/xterf==/colls/STuexopre=/", 
    "offerResourceId": "STuexopre=", 
    "id": "xiZw", 
    "_rid": "xiZw" 
} 

响应

HTTP/1.1 401 Unauthorized 
Transfer - Encoding: chunked 
Content - Type: application/json 
Content - Location: https: //mycosmosdb.documents.azure.com/offers/variantstockquantity 
Server: Microsoft - HTTPAPI/2.0 
x - ms - activity - id: 6f7be3c8 - cfa2 - 4d5e - ad69 - fb14ef218980 
Strict - Transport - Security: max - age = 31536000 
    x - ms - gatewayversion: version = 1.14.57.1 
    Date: Wed, 02 Aug 2017 08: 40: 35 GMT 

163{ 
    "code": "Unauthorized", 
    "message": "The input authorization token can't serve the request. Please check that the expected payload is built as per the protocol, and check the key being used. Server used the following payload to sign: 'put\noffers\mycollection\nwed, 02 aug 2017 08:40:37 gmt\n\n'\r\nActivityId: 6f7be3c8-cfa2-4d5e-ad69-fb14ef218980" 
} 
0 

我的PowerShell代码

Function Generate-MasterKeyAuthorizationSignature 
{ 
    [CmdletBinding()] 
    Param 
    (
     [Parameter(Mandatory=$true)][String]$verb, 
     [Parameter(Mandatory=$true)][String]$resourceLink, 
     [Parameter(Mandatory=$true)][String]$resourceType, 
     [Parameter(Mandatory=$true)][String]$dateTime, 
     [Parameter(Mandatory=$true)][String]$key, 
     [Parameter(Mandatory=$true)][String]$keyType, 
     [Parameter(Mandatory=$true)][String]$tokenVersion 
    ) 

    $hmacSha256 = New-Object System.Security.Cryptography.HMACSHA256 
    $hmacSha256.Key = [System.Convert]::FromBase64String($key) 

    If ($resourceLink -eq $resourceType) { 
     $resourceLink = "" 
    } 

    $payLoad = "$($verb.ToLowerInvariant())`n$($resourceType.ToLowerInvariant())`n$resourceLink`n$($dateTime.ToLowerInvariant())`n`n" 
    $hashPayLoad = $hmacSha256.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($payLoad)) 
    $signature = [System.Convert]::ToBase64String($hashPayLoad); 

    [System.Web.HttpUtility]::UrlEncode("type=$keyType&ver=$tokenVersion&sig=$signature") 
} 


Function Modify-Offer 
{ 
    [CmdletBinding()] 
    Param 
    (
     [Parameter(Mandatory=$true)][String]$DocumentDBApi, 
     [Parameter(Mandatory=$true)][String]$EndPoint, 
     [Parameter(Mandatory=$true)][String]$MasterKey, 
     [Parameter(Mandatory=$true)][String]$CollectionName 
    ) 


    $Verb = "PUT" 
    $ResourceType = "offers"; 
    $ResourceLink = "offers" 

    $body = '{ 
    "offerVersion": "V2", 
    "offerType": "Invalid", 
    "content": { 
     "offerThroughput": 500, 
     "offerIsRUPerMinuteThroughputEnabled": false 
    }, 
    "resource": "dbs/xterf==/colls/STuexopre=/", 
    "offerResourceId": "STuexopre=", 
    "id": "xiZw", 
    "_rid": "xiZw" 
}' 
    $dateTime = [DateTime]::UtcNow.ToString("r") 
    $authHeader = Generate-MasterKeyAuthorizationSignature -verb $Verb -resourceLink $ResourceLink -resourceType $ResourceType -key $MasterKey -keyType "master" -tokenVersion "1.0" -dateTime $dateTime 
    $header = @{authorization=$authHeader;"x-ms-version"=$DocumentDBApi;"x-ms-date"=$dateTime} 
    $contentType= "application/json" 
    $queryUri = "$EndPoint$ResourceLink/$CollectionName" 
    $result = Invoke-RestMethod -Method $Verb -ContentType $contentType -Uri $queryUri -Headers $header -Body $body 
    $result | ConvertTo-Json -Depth 10 

} 


Modify-Offer -EndPoint $CosmosDBEndPoint -MasterKey $MasterKey -DocumentDBApi $DocumentDBApiVersion -CollectionName $ColName 

有人可以给我一些帮助,为什么我的PUT请求由于授权错误而失败,我错过了什么以及如何纠正它。

回答

2

响应消息清楚地说明了用于验证的有效负载。在Generate-MasterKeyAuthorizationSignature中跟踪'$ payLoad'将很快解决这个问题。

你需要解决的,至少以下两个问题这个工作摆脱报价

  • RepalceOffer文档状态,而不是你是 通过集合名称。
  • ResourceLin硬编码:$ ResourceLink = Modify-Offer中的“offers”,因为它需要指向资源的RID。

这里被稍微修改代码应该做的工作

Function Generate-MasterKeyAuthorizationSignature 
{ 
    [CmdletBinding()] 
    Param 
    (
     [Parameter(Mandatory=$true)][String]$verb, 
     [Parameter(Mandatory=$true)][String]$resourceLink, 
     [Parameter(Mandatory=$true)][String]$resourceType, 
     [Parameter(Mandatory=$true)][String]$dateTime, 
     [Parameter(Mandatory=$true)][String]$key, 
     [Parameter(Mandatory=$true)][String]$keyType, 
     [Parameter(Mandatory=$true)][String]$tokenVersion 
    ) 

    $hmacSha256 = New-Object System.Security.Cryptography.HMACSHA256 
    $hmacSha256.Key = [System.Convert]::FromBase64String($key) 

    If ($resourceLink -eq $resourceType) { 
     $resourceLink = "" 
    } 

    $payLoad = "$($verb.ToLowerInvariant())`n$($resourceType.ToLowerInvariant())`n$resourceLink`n$($dateTime.ToLowerInvariant())`n`n" 
    $hashPayLoad = $hmacSha256.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($payLoad)) 
    $signature = [System.Convert]::ToBase64String($hashPayLoad); 
    Write-Host $payLoad 

    [System.Web.HttpUtility]::UrlEncode("type=$keyType&ver=$tokenVersion&sig=$signature") 
} 


Function Modify-Offer 
{ 
    [CmdletBinding()] 
    Param 
    (
     [Parameter(Mandatory=$true)][String]$DocumentDBApi, 
     [Parameter(Mandatory=$true)][String]$EndPoint, 
     [Parameter(Mandatory=$true)][String]$MasterKey, 
     [Parameter(Mandatory=$true)][String]$OfferRID 
    ) 


    $Verb = "PUT" 
    $ResourceType = "offers"; 

    $body = '{ 
    "offerVersion": "V2", 
    "offerType": "Invalid", 
    "content": { 
     "offerThroughput": 600, 
     "offerIsRUPerMinuteThroughputEnabled": false 
    }, 
"resource": "dbs/xterf==/colls/STuexopre=/", 
"offerResourceId": "STuexopre=", 
"id": "xiZw", 
"_rid": "xiZw" 
}' 
    $dateTime = [DateTime]::UtcNow.ToString("r") 
    $authHeader = Generate-MasterKeyAuthorizationSignature -verb $Verb -resourceLink $OfferRID -resourceType $ResourceType -key $MasterKey -keyType "master" -tokenVersion "1.0" -dateTime $dateTime 
    $header = @{authorization=$authHeader;"x-ms-version"=$DocumentDBApi;"x-ms-date"=$dateTime} 
    $contentType= "application/json" 
    $queryUri = "$EndPoint$ResourceType/$OfferRID" 
    $result = Invoke-RestMethod -Method $Verb -ContentType $contentType -Uri $queryUri -Headers $header -Body $body 
    $result | ConvertTo-Json -Depth 10 

} 

Modify-Offer -EndPoint $CosmosDBEndPoint -MasterKey $MasterKey -DocumentDBApi $DocumentDBApiVersion -OfferRID $ColName 

其他替代推荐的方法,如果可能的是消费客户端SDK在PowerShell中。以下是更新帐户第一次报价的示例代码。

Add-Type -Path "...\Microsoft.Azure.Documents.Client.dll" 
$client=New-Object Microsoft.Azure.Documents.Client.DocumentClient($CosmosDBEndPoint, $MasterKey) 
$offersEnum=$client.ReadOffersFeedAsync().Result.GetEnumerator(); 
if ($offersEnum.MoveNext()) 
{ 
    $targetOffer=$offersEnum.Current 
    $offerUpdated=New-Object Microsoft.Azure.Documents.OfferV2($targetOffer, 600, $FALSE) 
    $client.ReplaceOfferAsync($offerUpdated).Result 
} 
+0

谢谢@Kiran。您的意见非常感谢,现在它工作得很好。 我应该看到有效载荷。 我与RID混淆。该文件说RID,我期待_rid返回这是“xiZw”我需要通过的值,但我们仍然传递集合名称作为RID。这是否意味着offerRID与集合名称相同? 现在我们没有兴趣使用SDK,因为我们所有的部署服务器都需要这么做,所以我们考虑使用REST API。 – VidhyaSagar

+0

不好意思。对于SelfLink,RID可互换使用。对于您提供的产品,您只需要使用SelfLink。 –