SQL Server令牌缓存问题 [英] SQL Server Tokencache issue
问题描述
我基本上从这里获取了代码 https://github.com/Azure-Samples/active-directory-dotnet-webapp-webapi-multitenant-openidconnect/blob/master/TodoListWebApp/DAL/EFADALTokenCache.cs 但它不适合我的应用程序,因为我不需要示例中给出的每个用户的缓存。因此,我删除了接受User作为参数的构造函数,因为我希望缓存是全局的。我想出了这个版本:
I basically took code from here https://github.com/Azure-Samples/active-directory-dotnet-webapp-webapi-multitenant-openidconnect/blob/master/TodoListWebApp/DAL/EFADALTokenCache.cs but it is not suitable for my application as I don't need the cache per user as given in the example. Accordingly I removed the constructor that accepted User as a parameter since I wanted the cache to be global. I have came up with this version:
public class EFTestTokenCache : TokenCache
{
private TestEntities _TestEntities = new TestEntities();
private TestTokenCache _cache;
public EFTestTokenCache()
{
this.AfterAccess = AfterAccessNotification;
this.BeforeAccess = BeforeAccessNotification;
this.BeforeWrite = BeforeWriteNotification;
}
// clean up the DB
public override void Clear()
{
base.Clear();
foreach (var cacheEntry in _TestEntities.TestTokenCaches)
_TestEntities.TestTokenCaches.Remove(cacheEntry);
_TestEntities.SaveChanges();
}
// Notification raised before ADAL accesses the cache.
// This is your chance to update the in-memory copy from the DB, if the in-memory version is stale
void BeforeAccessNotification(TokenCacheNotificationArgs args)
{
if (_cache == null)
{
// first time access
_cache = _TestEntities.TestTokenCaches.FirstOrDefault(c => c.webUserUniqueId == args.DisplayableId);
}
else
{ // retrieve last write from the DB
var status = from e in _TestEntities.TestTokenCaches
where (e.webUserUniqueId == args.DisplayableId)
select new
{
LastWrite = e.LastWrite
};
// if the in-memory copy is older than the persistent copy
if (status.First().LastWrite > _cache.LastWrite)
//// read from from storage, update in-memory copy
{
_cache = _TestEntities.TestTokenCaches.FirstOrDefault(c => c.webUserUniqueId == args.DisplayableId);
}
}
this.Deserialize((_cache == null) ? null : _cache.cacheBits);
}
// Notification raised after ADAL accessed the cache.
// If the HasStateChanged flag is set, ADAL changed the content of the cache
void AfterAccessNotification(TokenCacheNotificationArgs args)
{
// if state changed
if (this.HasStateChanged)
{
if (_cache != null)
{
_cache.cacheBits = this.Serialize();
_cache.LastWrite = DateTime.Now;
}
else
{
_cache = new TestTokenCache
{
webUserUniqueId = args.DisplayableId,
cacheBits = this.Serialize(),
LastWrite = DateTime.Now
};
}
// update the DB and the lastwrite
_TestEntities.Entry(_cache).State = _cache.EntryId == 0 ? EntityState.Added : EntityState.Modified;
_TestEntities.SaveChanges();
this.HasStateChanged = false;
}
}
void BeforeWriteNotification(TokenCacheNotificationArgs args)
{
// if you want to ensure that no concurrent write take place, use this notification to place a lock on the entry
}
}
全局高速缓存还是它有bug,是否总是必须按照示例中的说明基于用户?
Do you think this would work fine as a global cache or is it buggy and always has to be user based as given in the example?
另一个查询是为什么要在中清除数据库Clear()
。这是否意味着每当应用程序池关闭或我的数据库将被清除时?
Another query is why is the database cleared in Clear()
. Does this mean whenever application pool shuts down or so my database would be cleared? That should not happen though.
不胜感激。
推荐答案
如果您尝试不考虑用户而尝试实现全局令牌缓存,那么我会看到您的代码有问题,因为代码正在使用$ web $ UniqueId来过滤
If you are trying to implement a global token cache irrespective of the user then I see an issue with your code as code is looking for any existing cache per the sign in user as code is using webUserUniqueId to filter
_TestEntities.TestTokenCaches.FirstOrDefault(c => c.webUserUniqueId == args.DisplayableId);
在正确的示例代码中,每个用户都有一组保存在数据库中的令牌(或(例如集合),这样当他们登录Web应用程序时,他们可以直接执行Web API调用而不必重新进行身份验证/重复同意。
In the correct sample code, every user has a set of tokens that are saved in a DB (or as collection), so that when they sign in to the web app they can directly perform their web API calls without having to re-authenticate/repeat consent.
我不是确定了为什么要这样做的目的,但是我认为,如果要为Web实现自定义令牌缓存,最好为登录的不同用户提供令牌之间理想的隔离级别。
I am not sure of the purpose why you want to do this but in my opinion if you are implementing a custom token cache for a web it would be good to provide the desirable level of isolation between tokens for different users signing in.
此外,Clear()方法通过删除db中的所有项目来清除缓存,但是GitHub示例中尚未调用此方法,您需要添加对authContext.TokenCache.clear( )从AccountController的SignOut()方法清除用户注销时的缓存。
Also, Clear() method clears the cache by deleting all the items in db but this method has not been called in the GitHub sample and you need to add a call to authContext.TokenCache.clear() from SignOut() method of AccountController to clear the cache on user signout.
这篇关于SQL Server令牌缓存问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!