使用Powershell-CosmosDb调用RESTAPI

使用Powershell-CosmosDb调用RESTAPI,api,powershell,azure,azure-cosmosdb,Api,Powershell,Azure,Azure Cosmosdb,我试图使用COSMOSDBRESTAPI部署cosmos数据库。我正在使用一个函数来构建授权标头,我从link获得了脚本。对于GET&POST来说,它工作得非常好,但是当我试图执行PUT命令时,我总是得到低于错误的结果 调用RestMethod:远程服务器返回错误:(401) 未经授权 我试图更新Cosmos系列的报价,但总是以错误告终,我不明白原因是什么。我还用Microsoft文档检查了我的标题和授权,看起来不错。请参阅所需的Uri和标头。我的要求和答复如下 请求 PUT https: //

我试图使用COSMOSDBRESTAPI部署cosmos数据库。我正在使用一个函数来构建授权标头,我从link获得了脚本。对于GET&POST来说,它工作得非常好,但是当我试图执行PUT命令时,我总是得到低于错误的结果

调用RestMethod:远程服务器返回错误:(401) 未经授权

我试图更新Cosmos系列的报价,但总是以错误告终,我不明白原因是什么。我还用Microsoft文档检查了我的标题和授权,看起来不错。请参阅所需的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
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
我的Powershell代码

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
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请求因授权错误而失败,我缺少了什么,以及我如何更正它。

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

您需要至少解决以下两个问题才能使其正常工作

  • RepalceOffer文档声明放弃该报价,而您是 传递集合名称
  • ResourceLin硬编码:$ResourceLink =“offers”在Modify Offer中,因为它需要指向资源的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
如果可能,推荐的其他替代方法是在Powershell中使用客户端SDK。下面是一个示例代码,用于更新帐户的第一个报价

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
}

谢谢你,基兰。非常感谢您的投入,现在效果很好。我也应该看看有效载荷。我和里德之间有点混淆。文档上写着RID,我希望返回的_RID是“xiZw”我需要传递的值,但我们仍然将集合名称作为RID传递。这是否意味着OfferId与集合名称相同?目前我们对使用SDK不感兴趣,因为在我们所有的部署服务器上都需要SDK,所以我们考虑使用RESTAPI。很抱歉给您带来混淆。RID可互换用于自链接。对于优惠,您只需要使用SelfLink。