【问题标题】:how to authenticate documentdb stored procedure REST call如何对 documentdb 存储过程 REST 调用进行身份验证
【发布时间】:2016-08-26 08:50:16
【问题描述】:

编辑:问题是parameters.ToString()。也像刘冷宁指出你需要添加'/sprocs/sprocname'

我正在尝试使用 ASP.NET Core 1.0 / C# 中的 REST 调用在 Azure DocumentDB 中执行存储过程。

我使用这个 MSDN 页面上的方法来生成哈希: https://msdn.microsoft.com/library/azure/dn783368.aspx

我收到了 401 Unauthorized 响应。 “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));
    }
}

【问题讨论】:

    标签: c# asp.net azure authentication azure-cosmosdb


    【解决方案1】:

    似乎当您生成身份验证令牌时,在 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
    

    【讨论】:

    • 如果我将 /sprocs/{storedProcedure} 添加到哈希中,我会收到错误请求。此外,我没有看到密钥被散列的方式有任何真正的区别。
    • 深入研究:问题是这样的:parameters.ToString()
    猜你喜欢
    • 1970-01-01
    • 2017-11-24
    • 2015-03-29
    • 1970-01-01
    • 2019-01-06
    • 2023-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多