2016-04-20 76 views
1

我正在使用.NET Core,因此無法使用Azure DocumentDb SDK。這就是爲什麼我想通過REST界面創建文檔的原因。我設法查詢數據庫,但是當我POST一個JSON文檔時,我得到一個未經授權的響應。這是我的代碼:通過REST在DocumentDb中創建文檔時未經授權

const string DatabaseId = "DB-id"; 
const string CollectionId = "UserSettings"; 
var documentDbUrl = "Injected via DI"; 
var authorizationKey = "Also injected; 

using (var httpClient = new HttpClient()) 
{ 
    var utcNow = DateTime.UtcNow; 
    httpClient.DefaultRequestHeaders.Add("x-ms-date", utcNow.ToString("r")); 
    httpClient.DefaultRequestHeaders.Add("x-ms-version", "2015-08-06"); 
    httpClient.DefaultRequestHeaders.Add("x-ms-documentdb-is-upsert", "true"); 

    var resourceLink = string.Format("dbs/{0}/colls/{1}/docs", DatabaseId, CollectionId); 
    var baseUrl = new Uri(documentDbUrl); 

    var masterKeyAuthorizationSignatureGenerator = new MasterKeyAuthorizationSignatureGenerator(); 
    var authHeader = masterKeyAuthorizationSignatureGenerator.Generate("POST", resourceLink, "docs", authorizationKey, "master", "1.0", utcNow); 
    httpClient.DefaultRequestHeaders.Add("authorization", authHeader); 

    var response = await httpClient.PostAsJsonAsync(new Uri(baseUrl, resourceLink), userSettings); 

    // at this point, response.StatusCode is Unauthorized 
} 

MasterKeyAuthorizationSignatureGenerator你看到沒有包含the logic to create the hash,查詢數據庫時的工作原理:

public string Generate(string verb, string resourceId, string resourceType, string key, string keyType, string tokenVersion, DateTime requestDateTime) 
{ 
    var hmacSha256 = new System.Security.Cryptography.HMACSHA256 { Key = Convert.FromBase64String(key) }; 

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

    var hashPayLoad = hmacSha256.ComputeHash(System.Text.Encoding.UTF8.GetBytes(payLoad)); 
    var signature = Convert.ToBase64String(hashPayLoad); 

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

我敢肯定,databaseid,collectionid,URL和重點是正確的。鍵和id是我用來查詢,這是有效的。當我更改url時,例如通過添加documentid(然後生成自己),我會得到另一條消息(MethodNotAllowed)。

更新:

使用郵差,我可以看到這是響應我得到:

{ 
    "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: 
       'post\ndocs\ndbs/MyDb/colls/MyColl\nsat, 23 apr 2016 09:44:39 gmt\n\n'\r\nActivityId: 1be76530-ad32-4b54-b96b-6e0d4ebbc851" 
} 

任何提示什麼,我做錯了或如何分析呢?

+0

使用捲曲,使你的代碼之外的請求時,它會快得多嘗試不同的東西。 – Joe

+0

我使用了Postman,並將響應放入我的更新中。 – Peter

回答

0

這是一個微妙的,但我用的是下面的資源ID生成散列我:

var resourceLink = string.Format("dbs/{0}/colls/{1}/docs", DatabaseId, CollectionId); 
// this becomes something like dbs/MyDb/colls/MyCollection/docs 

/docs應該被忽略。所以它變成:

var resourceLink = string.Format("dbs/{0}/colls/{1}", DatabaseId, CollectionId); 
// this becomes something like dbs/MyDb/colls/MyCollection 

但是,當我這樣做時,我得到一個方法不允許的響應。這是因爲我也在使用這個鏈接來發布帖子。但是帖子uri應該是包含/docs的鏈接。

所以我完整的代碼現在變爲:

const string DatabaseId = "DB-id"; 
const string CollectionId = "UserSettings"; 
var documentDbUrl = "Injected via DI"; 
var authorizationKey = "Also injected; 

using (var httpClient = new HttpClient()) 
{ 
    var utcNow = DateTime.UtcNow; 
    httpClient.DefaultRequestHeaders.Add("x-ms-date", utcNow.ToString("r")); 
    httpClient.DefaultRequestHeaders.Add("x-ms-version", "2015-08-06"); 
    httpClient.DefaultRequestHeaders.Add("x-ms-documentdb-is-upsert", "true"); 

    var resourceLink = string.Format("dbs/{0}/colls/{1}", DatabaseId, CollectionId); 
    var baseUrl = new Uri(documentDbUrl); 

    var masterKeyAuthorizationSignatureGenerator = new MasterKeyAuthorizationSignatureGenerator(); 
    var authHeader = masterKeyAuthorizationSignatureGenerator.Generate("POST", resourceLink, "docs", authorizationKey, "master", "1.0", utcNow); 
    httpClient.DefaultRequestHeaders.Add("authorization", authHeader); 

    var response = await httpClient.PostAsJsonAsync(new Uri(baseUrl, resourceLink + "/docs"), userSettings); 
} 
0

請注意,有兩種方法的URI來指定資源:

1) using the resource id. The id is user settable. 

2) using the resource _rid. This is the system generated id for the resource. 

當使用資源ID(方法1),則必須確保在級聯令牌的資源ID用於散列簽名令牌位於資源中使用的相同大小,因爲資源ID區分大小寫。例如,如果資源ID是集合的MyCollection,那麼資源ID應該完全是串聯標記中的MyCollection。

本文提供了構建哈希簽名令牌的其他詳細信息。 https://msdn.microsoft.com/en-us/library/azure/dn783368.aspx

+0

我添加了生成哈希的代碼。正如你所看到的,我沒有大寫或壓縮resourceId。 – Peter

相關問題