我在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都会接受它!
答案 0 :(得分:3)
原因是DocumentDB在令牌到期时有一些松弛,以允许客户端或服务器中潜在的时钟偏差。因为这个令牌在其真正的到期时间之后具有“宽限期”。允许的时钟偏差在5分钟内,这就是为什么你会看到你所做的行为。
您是否有特殊原因要创建一个仅在10秒内有效的令牌?
完全披露:我在DocumentDB工作。