2017-02-09 49 views
1

我在DocumentDb中遇到了一個奇怪的問題。 我創建了一個用戶和操作特定集合的權限。然後我爲該用戶請求了有限有效性的資源令牌。我通過將ResourceTokenExpirySeconds設置爲10秒來做到了這一點。爲了測試它,我爲了令牌過期而等待足夠多。但是,Azure接受使用該(據稱過期的)令牌的後續請求。Azure DocumentDB:有效期限後的資源令牌保持有效

考慮下面的代碼,它預計這一行失敗,但它並不:

UserPermissionExample.TestToken(10, 15); 

這裏是UserPermissionExample實現:

public class UserPermissionExample 
{ 
    const string endPoint = "https://[ENDPOINT].documents.azure.com"; 
    const string masterKey = "[PRIMARY-KEY]"; 
    const string dbName = "test-db"; 
    const string testUserId = "test-user"; 
    const string collName = "test-coll"; 

    public static async Task TestToken(int validity, int wait) 
    { 
     // Get a time-bound token 
     string token = await GetToken(validity /*seconds*/); 

     // Wait enough so the token gets expired 
     Thread.Sleep(TimeSpan.FromSeconds(wait)); 

     // Try to add a document with the expired token. It is expected to fail: 
     DocumentClient client = new DocumentClient(new Uri(endPoint), token); 
     await client.CreateDocumentAsync(
      UriFactory.CreateDocumentCollectionUri(dbName, collName), 
      new { name = "A test document" }); 
    } 

    static async Task<string> GetToken(int tokenValiditySeconds) 
    { 
     DocumentClient client = new DocumentClient(new Uri(endPoint), masterKey); 
     ResourceResponse<Database> db = await UpsertDb(client); 
     ResourceResponse<DocumentCollection> collection = await UpsertCollection(client, db); 

     var userUrl = UriFactory.CreateUserUri(dbName, "testuser"); 
     var user = await client.UpsertUserAsync(db.Resource.SelfLink, new User() { Id = testUserId }); 

     var permission = 
      await client.UpsertPermissionAsync(
       user.Resource.SelfLink, 
       new Permission() 
       { 
        Id = "PersmissionForTestUser", 
        PermissionMode = PermissionMode.All, 
        ResourceLink = collection.Resource.SelfLink, 
       }, 
       new RequestOptions() { ResourceTokenExpirySeconds = tokenValiditySeconds }); 

     permission = 
      await client.ReadPermissionAsync(
       permission.Resource.SelfLink, 
       new RequestOptions() { ResourceTokenExpirySeconds = tokenValiditySeconds }); 

     return permission.Resource.Token; 
    } 

    static async Task<ResourceResponse<DocumentCollection>> UpsertCollection(DocumentClient client, ResourceResponse<Database> db) 
    { 
     ResourceResponse<DocumentCollection> collection = null; 
     try 
     { 
      collection = await client.ReadDocumentCollectionAsync(UriFactory.CreateDocumentCollectionUri(dbName, collName)); 
     } 
     catch (DocumentClientException ex) 
     { 
      if (ex.StatusCode == System.Net.HttpStatusCode.NotFound) 
      { 
       collection = await client.CreateDocumentCollectionAsync(db.Resource.SelfLink, new DocumentCollection() { Id = collName }); 
      } 
     } 

     return collection; 
    } 

    static async Task<ResourceResponse<Database>> UpsertDb(DocumentClient client) 
    { 
     ResourceResponse<Database> db = null; 
     try 
     { 
      db = await client.ReadDatabaseAsync(UriFactory.CreateDatabaseUri(dbName)); 
     } 
     catch (DocumentClientException ex) 
     { 
      if (ex.StatusCode == System.Net.HttpStatusCode.NotFound) 
      { 
       db = await client.CreateDatabaseAsync(new Database() { Id = dbName }); 
      } 
     } 

     return db; 
    } 
} 

PS:我使用的是微軟.Azure.DocumentDB版本=「1.11.4」。

更新:我發現Azure在令牌發佈時間後5分鐘開始檢查令牌過期!然後它拒絕令牌。因此,在此期間之前,無論令牌是否過期,Azure都會接受它!

+0

既然你已經知道了這個問題,請發表一個正確的答案,而不是編輯你的問題。這樣,這個問題就可以適當地關閉了。 –

+0

@DavidMakogon這不是一個答案。我仍然反對寬限期。 – Alireza

回答

3

其原因在於DocumentDB在令牌期限中有一些鬆弛,以允許客戶端或服務器中可能存在時鐘偏差。由於這些令牌在其真正的到期時間之後有一個「寬限期」。允許的時鐘偏差在5分鐘內,這就是爲什麼你會看到你所做的行爲。

是否有一個特定的原因,你創建一個應該只有10秒有效的令牌?

完全披露:我在DocumentDB工作。

+0

感謝您的回答。首先,這種行爲是否記錄在案?其次,這個要求的原因是我想將特定文檔或集合的更新委託給另一個應用程序。 – Alireza

+1

它不僅是DocumentDB也是。時鐘偏移非常普遍,例如IoT Hub具有相同的5分鐘寬限期。 – juunas

+0

@juunas我明白了。似乎這種偏離來自Azure使用的JWT庫。你知道任何文件具體說明這一點嗎? – Alireza