Azure DocumentDB:有时间限制的资源令牌在到期时间后仍然有效

时间:2017-02-09 02:01:56

标签: azure azure-cosmosdb

我在DocumentDb面临一个奇怪的问题。 我创建了一个用户和操作特定集合的权限。然后我请求该用户的有效性有限的资源令牌。我通过将ResourceTokenExpirySeconds设置为10秒来完成此操作。为了测试它,我等待令牌过期。但是,Azure使用该(假定已过期)令牌接受后续请求。

考虑以下代码,预计此行会失败,但不会:

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:我正在使用Microsoft.Azure.DocumentDB version =“1.11.4”。

更新:我发现Azure在令牌发布时间后5分钟开始检查令牌到期!然后它拒绝令牌。因此,在此期间之前,无论令牌是否已过期,Azure都会接受它!

1 个答案:

答案 0 :(得分:3)

原因是DocumentDB在令牌到期时有一些松弛,以允许客户端或服务器中潜在的时钟偏差。因为这个令牌在其真正的到期时间之后具有“宽限期”。允许的时钟偏差在5分钟内,这就是为什么你会看到你所做的行为。

您是否有特殊原因要创建一个仅在10秒内有效的令牌?

完全披露:我在DocumentDB工作。