SQL Server令牌缓存问题 [英] SQL Server Tokencache issue

查看:110
本文介绍了SQL Server令牌缓存问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我基本上从这里获取了代码 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆