2016-08-26 5 views
1

EDIT: Проблема была в параметрах. ToString(). Также, как и Lengning Liu, вам нужно добавить '/ sprocs/sprocname'как аутентифицировать хранимую процедуру documentdb REST-вызов

Я пытаюсь выполнить хранимую процедуру в Azure DocumentDB с вызовом REST в ASP.NET Core 1.0/C#.

Я использую метод на этой странице MSDN для создания хэш: https://msdn.microsoft.com/library/azure/dn783368.aspx

Я получаю 401 Несанкционированное repsonse. Является ли «sprocs» правильным типом документа, или мне нужно вводить другой тип?

public class Database 
{ 

    public async Task<HttpResponseMessage> StoredProcedure(string database, string collection, string storedProcedure, string[] parameters) 
    { 
     //https://{databaseaccount}.documents.azure.com/dbs/{db-id}/colls/{coll-id}/sprocs/{sproc-name} 

     string resourceLink = $"dbs/{database}/colls/{collection}"; 
     var client = Client("POST", resourceLink, "sprocs"); 

     StringContent content = new StringContent(parameters.ToString(), null, "application/query+json"); 
     var uri = new Uri(_endpointUri, $"dbs/{database}/colls/{collection}/sprocs/{storedProcedure}"); 
     HttpResponseMessage response = await client.PostAsync(uri, content); 

     return response; 
    } 

    private HttpClient Client(string verb, string resourceLink, string resourceType) 
    { 
     var client = new HttpClient(); 
     var utc_date = DateTime.UtcNow.ToString("r"); 
     client.DefaultRequestHeaders.Add("x-ms-date", utc_date); 
     client.DefaultRequestHeaders.Add("x-ms-version", "2015-12-16"); 
     client.DefaultRequestHeaders.Add("x-ms-max-item-count", "10000"); 

     var authHeader = GenerateMasterKeyAuthorizationSignature(utc_date, verb, resourceLink, resourceType, _authorizationKey, "master", "1.0"); 

     client.DefaultRequestHeaders.Add("authorization", authHeader); 

     return client; 
    } 

    private static string GenerateMasterKeyAuthorizationSignature(string utc_date, string verb, string resourceId, string resourceType, string key, string keyType, string tokenVersion) 
    { 

     var hmacSha256 = new System.Security.Cryptography.HMACSHA256 { Key = Convert.FromBase64String(key) }; 

     string payLoad = string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}\n{1}\n{2}\n{3}\n{4}\n", 
       verb.ToLowerInvariant(), 
       resourceType.ToLowerInvariant(), 
       resourceId, 
       utc_date.ToLowerInvariant(), 
       "" 
     ); 

     byte[] hashPayLoad = hmacSha256.ComputeHash(System.Text.Encoding.UTF8.GetBytes(payLoad)); 
     string signature = Convert.ToBase64String(hashPayLoad); 

     return System.Net.WebUtility.UrlEncode(String.Format(System.Globalization.CultureInfo.InvariantCulture, "type={0}&ver={1}&sig={2}", 
      keyType, 
      tokenVersion, 
      signature)); 
    } 
} 

ответ

2

, кажется, что, когда вы сгенерировали маркер аутентификации, в RESOURCEID части, вы оставили из "/ sprocs/{StoredProcedure}". Вы включили его в uri, что является правильным.

У меня есть образец сценария powershell, который, надеюсь, также поможет вам узнать, как генерируется токен аутентификации.

Add-Type -AssemblyName System.Web 

$accountName = "<db account name>" 
$connectionKey = "<secret key>" 
$collectionName = "<coll name>" 
$databaseName = "<db name>" 

Write-host ("Account " + $accountName) 
Write-host ("Database " + $databaseName) 
Write-host ("Collection " + $collectionName) 


    function GetKey([System.String]$Verb = '',[System.String]$ResourceId = '', 
      [System.String]$ResourceType = '',[System.String]$Date = '',[System.String]$masterKey = '') { 
     $keyBytes = [System.Convert]::FromBase64String($masterKey) 
     $text = @($Verb.ToLowerInvariant() + "`n" + $ResourceType.ToLowerInvariant() + "`n" + $ResourceId + "`n" + $Date.ToLowerInvariant() + "`n" + "" + "`n") 
     $body =[Text.Encoding]::UTF8.GetBytes($text) 
     $hmacsha = new-object -TypeName System.Security.Cryptography.HMACSHA256 -ArgumentList (,$keyBytes) 
     $hash = $hmacsha.ComputeHash($body) 
     $signature = [System.Convert]::ToBase64String($hash) 

     Write-Host($text) 

     [System.Web.HttpUtility]::UrlEncode($('type=master&ver=1.0&sig=' + $signature)) 

    } 

    function GetUTDate() { 
     $date = get-date 
     $date = $date.ToUniversalTime(); 
     return $date.ToString("r", [System.Globalization.CultureInfo]::InvariantCulture); 
    } 

    function GetDatabases() { 
     $uri = $rootUri + "/dbs" 

     $hdr = BuildHeaders -resType dbs 

     $response = Invoke-RestMethod -Uri $uri -Method Get -Headers $hdr 
     $response.Databases 

     Write-Host ("Found " + $Response.Databases.Count + " Database(s)") 

    } 

    function GetCollections([string]$dbname){ 
     $uri = $rootUri + "/" + $dbname + "/colls" 
     $headers = BuildHeaders -resType colls -resourceId $dbname 
     $response = Invoke-RestMethod -Uri $uri -Method Get -Headers $headers 
     $response.DocumentCollections 
     Write-Host ("Found " + $Response.DocumentCollections.Count + " DocumentCollection(s)") 
    } 

    function BuildHeaders([string]$action = "get",[string]$resType, [string]$resourceId){ 
     $authz = GetKey -Verb $action -ResourceType $resType -ResourceId $resourceId -Date $apiDate -masterKey $connectionKey 
     $headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]" 
     $headers.Add("Authorization", $authz) 
     $headers.Add("x-ms-version", '2015-12-16') 
     $headers.Add("x-ms-date", $apiDate) 
     $headers 
    } 

    function PostDocument([string]$document, [string]$dbname, [string]$collection){ 
     $collName = "dbs/"+$dbname+"/colls/" + $collection 
     $headers = BuildHeaders -action Post -resType docs -resourceId $collName 
     $headers.Add("x-ms-documentdb-is-upsert", "true") 
     $uri = $rootUri + "/" + $collName + "/docs" 

     Write-host ("Calling " + $uri) 

     $response = Invoke-RestMethod $uri -Method Post -Body $json -ContentType 'application/json' -Headers $headers 
     $response 
    } 

    function PostSprocQuery([string]$dbname, [string]$collection){ 
     $sprocName = "dbs/"+$dbname+"/colls/" + $collection + "/sprocs/samplesproc" 
     $headers = BuildHeaders -action Post -resType sprocs -resourceId $sprocName 
     $uri = $rootUri + "/" + $sprocName 

     Write-host ("Calling " + $uri) 
     write-host $authz 
     write-host $apiDate 

     $response = Invoke-RestMethod $uri -Method Post -Body $json -ContentType 'application/json' -Headers $headers 
     $response 
    } 

    $rootUri = "https://" + $accountName + ".documents.azure.com" 
    write-host ("Root URI is " + $rootUri) 

    #validate arguments 

    $apiDate = GetUTDate 

    $db = GetDatabases | where { $_.id -eq $databaseName } 

    if ($db -eq $null) { 
     write-error "Could not find database in account" 
     return 
    } 

    $dbname = "dbs/" + $databaseName 
    $collection = GetCollections -dbname $dbname | where { $_.id -eq $collectionName } 

    if($collection -eq $null){ 
     write-error "Could not find collection in database" 
     return 
    } 

    $json = @" 
{ 
    "id": "3" 
} 
"@ 
    PostDocument -document $json -dbname $databaseName -collection $collectionName 

    $json = @" 
[ 
    "samplesproc" 
] 
"@ 
    PostSprocQuery -document $json -dbname $databaseName -collection $collectionName 
+0

Если я добавлю/sprocs/{storedProcedure} в хэш, я получаю неверный запрос. Кроме того, я не вижу никакой реальной разницы в том, как ключ хэшируется. – Ben

+0

Dived глубже в него: проблема была в этом: parameters.ToString() – Ben

Смежные вопросы