【问题标题】:SQL Server Tokencache issueSQL Server 令牌缓存问题
【发布时间】:2018-07-24 14:20:37
【问题描述】:

我基本上从这里https://github.com/Azure-Samples/active-directory-dotnet-webapp-webapi-multitenant-openidconnect/blob/master/TodoListWebApp/DAL/EFADALTokenCache.cs 获取代码,但它不适合我的应用程序,因为我不需要示例中给出的每个用户的缓存。因此,我删除了接受 User 作为参数的构造函数,因为我希望缓存是全局的。我想出了这个版本:

 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
        }
}

您认为这作为全局缓存可以正常工作,还是它有问题并且总是必须基于示例中给出的用户?

另一个查询是为什么Clear() 中的数据库被清除。这是否意味着每当应用程序池关闭或我的数据库将被清除?但这不应该发生。

感谢任何帮助。

【问题讨论】:

    标签: c# entity-framework azure azure-active-directory powerbi


    【解决方案1】:

    如果您尝试实现不考虑用户的全局令牌缓存,那么我发现您的代码存在问题,因为代码正在为每个登录用户查找任何现有缓存 因为代码使用 webUserUniqueId 来过滤

    _TestEntities.TestTokenCaches.FirstOrDefault(c => c.webUserUniqueId == args.DisplayableId);
    

    在正确的示例代码中,每个用户都有一组保存在数据库(或作为集合)中的令牌,因此当他们登录到 Web 应用程序时,他们可以直接执行 Web API 调用,而无需重新- 验证/重复同意。

    我不确定您为什么要这样做,但在我看来,如果您正在为 Web 实现自定义令牌缓存,最好为登录的不同用户提供所需的令牌之间的隔离级别。

    此外,Clear() 方法通过删除 db 中的所有项目来清除缓存,但在 GitHub 示例中尚未调用此方法,您需要从 SignOut() 方法中添加对 authContext.TokenCache.clear() 的调用AccountController 在用户退出时清除缓存。

    【讨论】:

      猜你喜欢
      • 2013-07-26
      • 1970-01-01
      • 1970-01-01
      • 2015-10-08
      • 2013-08-05
      • 2012-08-13
      • 1970-01-01
      • 2018-05-06
      • 2015-08-28
      相关资源
      最近更新 更多