【发布时间】:2020-03-29 11:02:51
【问题描述】:
我正在处理与向 Azure AD 进行身份验证的 ASP.NET Web 窗体应用程序中的 OpenId Connect 中间件 (OWIN) 相关的错误。我对 OWIN 和 OpenID 完全陌生,并没有编写此代码,所以请耐心等待。
该解决方案已经过测试,看起来运行良好,但一旦投入生产,我们就会看到多个空引用异常,因为调用 SecurityTokenValidated 通知中间件时 HttpContex.Current 为空。
在用户尝试登录生产环境的时间中,大约 30%-40% 的时间似乎都会出现此问题。我们最初无法在本地重现该问题,但我们最终发现,通过将 Chrome 中的网络速度设置为 Fast/Slow 3G 速度(很有趣),我们可以 100% 地重现该问题。
这是我们在 Startup.cs 类中配置中间件的代码:
[assembly: OwinStartup(typeof(Namespace.Startup))]
namespace Namespace
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
var openIdConnectProvider = OpenIdConnectProviderDAO.GetOpenIdConnectProviders().Single(x => x.ClientId == "ClientIdHere");
app.Use((context, next) =>
{
var httpContext = context.Get<HttpContextBase>(typeof(HttpContextBase).FullName);
httpContext.SetSessionStateBehavior(SessionStateBehavior.Required);
return next();
});
app.UseStageMarker(PipelineStage.MapHandler);
app.SetDefaultSignInAsAuthenticationType(OpenIdConnectAuthenticationDefaults.AuthenticationType);
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
ClientId = openIdConnectProvider.ClientId,
Authority = openIdConnectProvider.Authority,
RedirectUri = ConfigurationHelper.GetAppSetting("applicationRoot").ToLower(),
AuthenticationType = openIdConnectProvider.Key,
AuthenticationMode = AuthenticationMode.Passive,
ResponseType = OpenIdConnectResponseType.IdToken,
Scope = OpenIdConnectScope.Email,
TokenValidationParameters = new TokenValidationParameters
{
ValidIssuer = openIdConnectProvider.ValidIssuer,
ValidateIssuer = true,
ValidAudience = openIdConnectProvider.ClientId,
ValidateAudience = true
},
Notifications = new OpenIdConnectAuthenticationNotifications
{
SecurityTokenValidated = OnSecurityTokenValidated,
AuthenticationFailed = OnAuthenticationFailed
}
});
}
private Task OnSecurityTokenValidated(SecurityTokenValidatedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> arg)
{
// This is null when connection speed is set to Slow/Fast 3G
var context = HttpContext.Current;
return Task.FromResult(0);
}
private Task OnAuthenticationFailed(AuthenticationFailedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> context)
{
context.HandleResponse();
context.Response.Redirect("Login.aspx");
return Task.FromResult(0);
}
}
}
我们需要访问 HttpContext.Current 才能访问 SecurityTokenValidated 中间件中的 Session。所以我们按照这些帖子中的建议添加了中间件:
Can OWIN middleware use the http session?
HttpContext.Current.Session is null + OWIN
这看起来效果很好,直到问题开始在生产中出现。
我尝试在各种 PipelinesStages(Authenticate、PostAcquireState 等)中使用不同的 UseStageMarker 组合,但都没有奏效。
任何帮助将不胜感激!
【问题讨论】:
-
嗨@Abragsta。你能解决这个问题吗?
-
不,很遗憾我无法解决这个问题。不确定是代码还是服务器有问题。但是我们现在要更改生产服务器,所以也许这会有所帮助。当我们尝试过时会发布更新。
标签: webforms azure-active-directory owin openid-connect owin-middleware