gpt4 book ai didi

c# - 使用 Katana OpenID Connect 中间件解决 OnSendingHeaders 死锁

转载 作者:太空狗 更新时间:2023-10-29 23:30:23 25 4
gpt4 key购买 nike

我正在尝试使用 Katana 项目提供的 OpenID Connect 身份验证中间件。

实现中存在一个错误,在这些情况下会导致死锁:

  1. 在请求具有线程亲和性的主机(例如 IIS)中运行。
  2. 尚未检索到 OpenID Connect 元数据文档或缓存副本已过期。
  3. 应用调用 SignOut 用于身份验证方法。
  4. 应用程序中发生的操作导致写入响应流。

死锁的发生是由于身份验证中间件处理来自主机的回调信号( header 已发送)的方式。问题的根源在于这个方法:

private static void OnSendingHeaderCallback(object state)
{
AuthenticationHandler handler = (AuthenticationHandler)state;
handler.ApplyResponseAsync().Wait();
}

来自 Microsoft.Owin.Security.Infrastructure.AuthenticationHandler

调用Task.Wait()只有在返回 Task 时才是安全的已经完成,而在 OpenID Connect 中间件的情况下还没有完成。

中间件使用 Microsoft.IdentityModel.Protocols.ConfigurationManager<T> 的一个实例管理其配置的缓存副本。这是使用 SemaphoreSlim 的异步实现作为异步锁和 HTTP 文档检索器来获取配置。我怀疑这是死锁的触发因素 Wait()打电话。

这是我怀疑是原因的方法:

public async Task<T> GetConfigurationAsync(CancellationToken cancel)
{
DateTimeOffset now = DateTimeOffset.UtcNow;
if (_currentConfiguration != null && _syncAfter > now)
{
return _currentConfiguration;
}

await _refreshLock.WaitAsync(cancel);
try
{
Exception retrieveEx = null;
if (_syncAfter <= now)
{
try
{
// Don't use the individual CT here, this is a shared operation that shouldn't be affected by an individual's cancellation.
// The transport should have it's own timeouts, etc..

_currentConfiguration = await _configRetriever.GetConfigurationAsync(_metadataAddress, _docRetriever, CancellationToken.None);
Contract.Assert(_currentConfiguration != null);
_lastRefresh = now;
_syncAfter = DateTimeUtil.Add(now.UtcDateTime, _automaticRefreshInterval);
}
catch (Exception ex)
{
retrieveEx = ex;
_syncAfter = DateTimeUtil.Add(now.UtcDateTime, _automaticRefreshInterval < _refreshInterval ? _automaticRefreshInterval : _refreshInterval);
}
}

if (_currentConfiguration == null)
{
throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10803, _metadataAddress ?? "null"), retrieveEx);
}

// Stale metadata is better than no metadata
return _currentConfiguration;
}
finally
{
_refreshLock.Release();
}
}

我试过添加 .ConfigureAwait(false)到所有等待的操作,以努力将延续编码到线程池,而不是 ASP.NET 工作线程,但我在避免死锁方面没有取得任何成功。

我可以解决更深层次的问题吗?我不介意更换组件 - 我已经创建了自己的 IConfiguratioManager<T> 实验性实现.是否有可用于防止死锁的简单修复?

最佳答案

@悲剧 Actor 我们针对此问题采取了这些修复措施。您能否更新并查看问题是否仍然存在(我们认为我们已经用 184 修复了它,但正如您所见,我们有 185)。另一位客户使用最新的 nuget 取得了成功。

http://www.nuget.org/packages/Microsoft.IdentityModel.Protocol.Extensions/1.0.2.206221351

https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/pull/185/files

https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/pull/184/files

关于c# - 使用 Katana OpenID Connect 中间件解决 OnSendingHeaders 死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31243412/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com