OpenID 身份验证和自定义中间件在 Mono Linux 上引发异常
14
0
我有一个现有的 ASP.NET 4.5 应用程序(当前在 Windows 上运行),我们正尝试使用 Linux 容器将其部署在 Mono(版本 6.12.0)上。它托管在带有 Ngi 的 mono-fastcgi-server4 上...
我有一个现有的 ASP.NET 4.5 应用程序(当前在 Windows 上运行),我们正尝试使用 Linux 容器将其部署在 Mono(版本 6.12.0)上。它托管在 mono-fastcgi-server4 上,使用 Nginx 作为反向代理。该项目使用标准 OpenIdConnectAuthentication 中间件以及一些自定义中间件,例如 URLRewriting、TrackRequest 等。当我第一次尝试访问该应用程序时,会记录以下异常,并在 UI 上显示 401 Unauthorized 错误。该应用程序在 Windows 上运行正常,没有任何错误。
Exception: Operation is not valid due to the current state of the object.
Stack trace: at Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.IntegratedPipelineContext.PushLastObjects (System.Collections.Generic.IDictionary`2[TKey,TValue] environment, System.Threading.Tasks.TaskCompletionSource`1[TResult] completionSource) [0x0002c] in /_/src/Microsoft.Owin.Host.SystemWeb/IntegratedPipeline/IntegratedPipelineContext.cs:220
at Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.IntegratedPipelineContext.PrepareInitialContext (System.Web.HttpApplication application) [0x0001f] in /_/src/Microsoft.Owin.Host.SystemWeb/IntegratedPipeline/IntegratedPipelineContext.cs:175
at Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.IntegratedPipelineContextStage.BeginEvent (System.Object sender, System.EventArgs e, System.AsyncCallback cb, System.Object extradata) [0x00088] in /_/src/Microsoft.Owin.Host.SystemWeb/IntegratedPipeline/IntegratedPipelineContextStage.cs:54
at System.Web.HttpApplication+<RunHooks>d__217.MoveNext () [0x000a4] in <e2b26a007ab7439ab0e922614212bb68>:0
at System.Web.HttpApplication+<Pipeline>d__225.MoveNext () [0x001ab] in <e2b26a007ab7439ab0e922614212bb68>:0
at System.Web.HttpApplication.Tick () [0x00000] in <e2b26a007ab7439ab0e922614212bb68>:0
System.Web.HttpException (0x80004005): headers have already been sent
at System.Web.HttpResponse.set_StatusCode (System.Int32 value) [0x00012] in <e2b26a007ab7439ab0e922614212bb68>:0
at System.Web.HttpResponseWrapper.set_StatusCode (System.Int32 value) [0x00000] in <e2b26a007ab7439ab0e922614212bb68>:0
at Microsoft.Owin.Host.SystemWeb.OwinCallContext.Microsoft.Owin.Host.SystemWeb.CallEnvironment.AspNetDictionary.IPropertySource.SetResponseStatusCode (System.Int32 value) [0x00000] in /_/src/Microsoft.Owin.Host.SystemWeb/OwinCallContext.Environment.cs:133
at Microsoft.Owin.Host.SystemWeb.CallEnvironment.AspNetDictionary.set_ResponseStatusCode (System.Int32 value) [0x00000] in /_/src/Microsoft.Owin.Host.SystemWeb/CallEnvironment/AspNetDictionary.Generated.cs:368
at Microsoft.Owin.Host.SystemWeb.CallEnvironment.AspNetDictionary.PropertiesTrySetValue (System.String key, System.Object value) [0x00257] in /_/src/Microsoft.Owin.Host.SystemWeb/CallEnvironment/AspNetDictionary.Generated.cs:1336
at Microsoft.Owin.Host.SystemWeb.CallEnvironment.AspNetDictionary.System.Collections.Generic.IDictionary<System.String,System.Object>.set_Item (System.String key, System.Object value) [0x00000] in /_/src/Microsoft.Owin.Host.SystemWeb/CallEnvironment/AspNetDictionary.cs:50
at Microsoft.Owin.OwinResponse.Set[T] (System.String key, T value) [0x00000] in /_/src/Microsoft.Owin/OwinResponse.cs:337
at Microsoft.Owin.OwinResponse.set_StatusCode (System.Int32 value) [0x00000] in /_/src/Microsoft.Owin/OwinResponse.cs:67
at Microsoft.Owin.OwinResponse.Redirect (System.String location) [0x00000] in /_/src/Microsoft.Owin/OwinResponse.cs:223
at SI.Frontend.BIF.Middleware.AuthHandler.ApplyResponseChallengeAsync () [0x0054e] in C:\TFSRoot\core-360Frontend\Web\SI.Frontend.BIF\Middleware\OpenIdConnectAuthenticationMiddleware.cs:612
at Microsoft.Owin.Security.Infrastructure.AuthenticationHandler.ApplyResponseCoreAsync () [0x0007f] in /_/src/Microsoft.Owin.Security/Infrastructure/AuthenticationHandler.cs:179
at Microsoft.Owin.Security.Infrastructure.AuthenticationHandler.ApplyResponseAsync () [0x0009c] in /_/src/Microsoft.Owin.Security/Infrastructure/AuthenticationHandler.cs:167
at Microsoft.Owin.Security.Infrastructure.AuthenticationHandler.TeardownAsync () [0x00024] in /_/src/Microsoft.Owin.Security/Infrastructure/AuthenticationHandler.cs:95
at Microsoft.Owin.Security.Infrastructure.AuthenticationMiddleware`1[TOptions].Invoke (Microsoft.Owin.IOwinContext context) [0x0017e] in /_/src/Microsoft.Owin.Security/Infrastructure/AuthenticationMiddleware.cs:32
at Microsoft.Owin.Security.Infrastructure.AuthenticationMiddleware`1[TOptions].Invoke (Microsoft.Owin.IOwinContext context) [0x0011b] in /_/src/Microsoft.Owin.Security/Infrastructure/AuthenticationMiddleware.cs:30
at SI.Frontend.BIF.Middleware.OTPAuthenticationMiddleware.Invoke (System.Collections.Generic.IDictionary`2[TKey,TValue] environment) [0x0015b] in C:\TFSRoot\core-360Frontend\Web\SI.Frontend.BIF\Middleware\OTPAuthenticationMiddleware.cs:46
如果我刷新页面,它会触发身份验证过程,允许我使用 OpenID 进行身份验证。之后,会记录与自定义中间件相关的另一个异常,如下所述。但是,页面在 UI 上可见。
System.NotImplementedException: The method or operation is not implemented.
at System.Web.HttpResponseBase.BeginFlush (System.AsyncCallback callback, System.Object state) [0x00000] in <e2b26a007ab7439ab0e922614212bb68>:0
at System.Threading.Tasks.TaskFactory`1[TResult].FromAsyncImpl (System.Func`3[T1,T2,TResult] beginMethod, System.Func`2[T,TResult] endFunction, System.Action`1[T] endAction, System.Object state, System.Threading.Tasks.TaskCreationOptions creationOptions) [0x000f6] in <d636f104d58046fd9b195699bcb1a744>:0
at System.Threading.Tasks.TaskFactory.FromAsync (System.Func`3[T1,T2,TResult] beginMethod, System.Action`1[T] endMethod, System.Object state, System.Threading.Tasks.TaskCreationOptions creationOptions) [0x00000] in <d636f104d58046fd9b195699bcb1a744>:0
at System.Threading.Tasks.TaskFactory.FromAsync (System.Func`3[T1,T2,TResult] beginMethod, System.Action`1[T] endMethod, System.Object state) [0x00000] in <d636f104d58046fd9b195699bcb1a744>:0
at Microsoft.Owin.Host.SystemWeb.CallStreams.OutputStream.FlushAsync (System.Threading.CancellationToken cancellationToken) [0x0001b] in /_/src/Microsoft.Owin.Host.SystemWeb/CallStreams/OutputStream.cs:135
at Microsoft.Owin.Mapping.MapMiddleware.Invoke (System.Collections.Generic.IDictionary`2[TKey,TValue] environment) [0x000c8] in /_/src/Microsoft.Owin/Mapping/MapMiddleware.cs:65
at SI.Frontend.BIF.Middleware.TrackRequestMiddleware.Invoke (System.Collections.Generic.IDictionary`2[TKey,TValue] environment) [0x00068] in C:\TFSRoot\core-360Frontend\Web\SI.Frontend.BIF\Middleware\TrackRequestMiddleware.cs:35
at SI.Frontend.BIF.Middleware.GetStartedPageCookiesMiddleware.Invoke (System.Collections.Generic.IDictionary`2[TKey,TValue] environment) [0x0008f] in C:\TFSRoot\core-360Frontend\Web\SI.Frontend.BIF\Middleware\GetStartedPageCookiesMiddleware.cs:32
at SI.Frontend.BIF.Middleware.URLRewriteMiddlewareBase.Invoke (System.Collections.Generic.IDictionary`2[TKey,TValue] environment) [0x00078] in C:\TFSRoot\core-360Frontend\Web\SI.Frontend.BIF\Middleware\URLRewrite\URLRewriteMiddlewareBase.cs:40
at Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.IntegratedPipelineContextStage.RunApp (System.Func`2[T,TResult] entryPoint, System.Collections.Generic.IDictionary`2[TKey,TValue] environment, System.Threading.Tasks.TaskCompletionSource`1[TResult] tcs, Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.StageAsyncResult result) [0x00024] in /_/src/Microsoft.Owin.Host.SystemWeb/IntegratedPipeline/IntegratedPipelineContextStage.cs:84
at SI.Frontend.BIF.Middleware.URLRewriteMiddlewareBase.Invoke (System.Collections.Generic.IDictionary`2[TKey,TValue] environment) [0x00078] in C:\TFSRoot\core-360Frontend\Web\SI.Frontend.BIF\Middleware\URLRewrite\URLRewriteMiddlewareBase.cs:40
at Microsoft.Owin.Security.Infrastructure.AuthenticationMiddleware`1[TOptions].Invoke (Microsoft.Owin.IOwinContext context) [0x0011b] in /_/src/Microsoft.Owin.Security/Infrastructure/AuthenticationMiddleware.cs:30
at Microsoft.Owin.Security.Infrastructure.AuthenticationMiddleware`1[TOptions].Invoke (Microsoft.Owin.IOwinContext context) [0x0011b] in /_/src/Microsoft.Owin.Security/Infrastructure/AuthenticationMiddleware.cs:30
at SI.Frontend.BIF.Middleware.OTPAuthenticationMiddleware.Invoke (System.Collections.Generic.IDictionary`2[TKey,TValue] environment) [0x0015b] in C:\TFSRoot\core-360Frontend\Web\SI.Frontend.BIF\Middleware\OTPAuthenticationMiddleware.cs:46
at Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.IntegratedPipelineContextStage.RunApp (System.Func`2[T,TResult] entryPoint, System.Collections.Generic.IDictionary`2[TKey,TValue] environment, System.Threading.Tasks.TaskCompletionSource`1[TResult] tcs, Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.StageAsyncResult result) [0x00024] in /_/src/Microsoft.Owin.Host.SystemWeb/IntegratedPipeline/IntegratedPipelineContextStage.cs:84
at Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.IntegratedPipelineContext.DoFinalWork (Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.StageAsyncResult result) [0x00025] in /_/src/Microsoft.Owin.Host.SystemWeb/IntegratedPipeline/IntegratedPipelineContext.cs:152
at Microsoft.Owin.Host.SystemWeb.Infrastructure.ErrorState.Rethrow () [0x00000] in /_/src/Microsoft.Owin.Host.SystemWeb/Infrastructure/ErrorState.cs:26
at Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.StageAsyncResult.End (System.IAsyncResult ar) [0x0001d] in /_/src/Microsoft.Owin.Host.SystemWeb/IntegratedPipeline/StageAsyncResult.cs:76
at Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.IntegratedPipelineContext.EndFinalWork (System.IAsyncResult ar) [0x00006] in /_/src/Microsoft.Owin.Host.SystemWeb/IntegratedPipeline/IntegratedPipelineContext.cs:167
at System.Web.AsyncInvoker.<doAsyncCallback>b__8_0 (System.Object ores) [0x00007] in <e2b26a007ab7439ab0e922614212bb68>:0
下面是代码:
[assembly: OwinStartup(typeof(SI.Frontend.Web.ConfigureFrontend), "Configure")]
namespace SI.Frontend.Web
{
public class ConfigureFrontend
{
public void Configure(IAppBuilder app)
{
AppStartup.InitializeApplication(); // BIF initialization etc.
ConfigureAuthentication(app);
app.UseStageMarker(PipelineStage.Authenticate);
ConfigureFrontendCore.ConfigureMiddleware(app);
app.Use<URLRewriteMiddlewarePreAuthenticate>();
app.UseStageMarker(PipelineStage.Authenticate);
app.Use<URLRewriteMiddlewarePostAuthenticate>();
app.Use<LanguageMappingMiddleware>();
app.Use<GetStartedPageCookiesMiddleware>();
app.Use<TrackRequestMiddleware>();
app.Use<IeBlockerMiddleware>();
app.UseStageMarker(PipelineStage.AcquireState);
}
private static void ConfigureAuthentication(IAppBuilder app)
{
// Configure authentication pipeline
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.Use<OTPAuthenticationMiddleware>();
var appConfigHelper = AppConfigHelper.Instance;
var authenticationMode = appConfigHelper.Get<string>("AuthenticationMode");
string cookieName = SI.Frontend.BIF.Authentication.Constants.ShortLivedWindowsAuthToken;
switch (authenticationMode.ToLowerInvariant())
{
case "federation":
cookieName = SI.Frontend.BIF.Authentication.Constants.WSFedTokenIdCookieName;
break;
case "openid":
cookieName = SI.Frontend.BIF.Authentication.Constants.JwtTokenCookieName;
break;
}
var provider = new CookieAuthenticationProvider();
provider.OnException = x =>
{
if (x.Exception != null && x.Exception.GetType() == typeof(TokenNotFoundException))
{
// This should never happen (the TokenStore lifetime should always outlive the cookie) - but in case it does, forcefully remove the cookie and redirect.
// For some reason, the cookie is not deleted if we just redirect to the current path, so we redirect to the root path just to be safe.
x.Rethrow = false;
x.Response.Cookies.Delete(cookieName);
x.Response.Redirect("/");
}
};
var options = new CookieAuthenticationOptions() {
SessionStore = new TokenStoreAuthenticationSessionStore(),
CookieName = cookieName,
Provider = provider,
SlidingExpiration = true,
CookieManager = new SameSiteCookieManager(new SystemWebCookieManager())
};
var authInfo = appConfigHelper.GetAuthenticationInfo();
if (authInfo.AuthType != AuthProtocol.OAuth)
{
options.ExpireTimeSpan = TokenStore.GetTokenLifetimeInCache().Add(new TimeSpan(0, -10, 0));
options.SlidingExpiration = false;
}
app.UseCookieAuthentication(options);
switch (authenticationMode.ToLowerInvariant())
{
case "openid":
ConfigureOpenIDConnect(app, appConfigHelper, authInfo);
break;
}
}
private static void ConfigureOpenIDConnect(IAppBuilder app, AppConfigHelper appConfigHelper, AuthInfo authInfo)
{
var scopes = "openid profile";
var additionalScopes = appConfigHelper.Get<string>("OpenIDAdditionalScopes");
if (!string.IsNullOrEmpty(additionalScopes))
scopes += " " + additionalScopes;
var publicUrl = appConfigHelper.Get<string>("SI.360.PublicUrl");
var userIdentityClaim = appConfigHelper.Get<string>("UserIdentityClaim");
var responseMode = appConfigHelper.Get<string>("OpenIDResponseMode");
var options = new OpenIdConnectAuthenticationOptions() {
CookieManager = new SameSiteCookieManager(new SystemWebCookieManager()),
MetadataAddress = appConfigHelper.Get<string>("DiscoveryAddress"),
ClientId = appConfigHelper.Get<string>("OpenIDClientID"),
ClientSecret = appConfigHelper.Get<string>("OpenIDClientSecret"),
Scope = scopes,
RedirectUri = publicUrl.TrimEnd('/') + "/_layouts/si/loginresponse.aspx",
UseTokenLifetime = true,
ResponseType = "code",
SignInAsAuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
RedeemCode = true,
SaveTokens = true,
TokenValidationParameters = new TokenValidationParameters() {
NameClaimType = userIdentityClaim
},
Notifications = new OpenIdConnectAuthenticationNotifications() {
SecurityTokenValidated = async x =>
{
x.AuthenticationTicket.Properties.IsPersistent = true;
if (authInfo.AuthType == AuthProtocol.OAuth)
{
var lifetime = 3600;
if (x.ProtocolMessage.Parameters.ContainsKey("expires_in"))
lifetime = int.Parse(x.ProtocolMessage.Parameters["expires_in"]);
x.AuthenticationTicket.Properties.ExpiresUtc = x.AuthenticationTicket.Properties.IssuedUtc.Value.AddSeconds(lifetime);
x.AuthenticationTicket.Properties.AllowRefresh = true;
}
else
{
x.AuthenticationTicket.Properties.ExpiresUtc = DateTimeOffset.Now.Add(TokenStore.GetTokenLifetimeInCache()).AddMinutes(-10);
}
var identity = x.AuthenticationTicket.Identity;
if (!identity.HasClaim(_ => _.Type == userIdentityClaim))
{
var config = await x.Options.ConfigurationManager.GetConfigurationAsync(new CancellationToken());
var accessToken = x.ProtocolMessage.AccessToken;
var userInfoResponse = await x.Options.Backchannel.GetUserInfoAsync(new UserInfoRequest() {
Address = config.UserInfoEndpoint,
Token = accessToken
});
foreach (var c in userInfoResponse.Claims)
{
if (!identity.HasClaim(_ => _.Type == c.Type))
x.AuthenticationTicket.Identity.AddClaim(c);
}
}
}
}
};
if (!string.IsNullOrWhiteSpace(responseMode))
options.ResponseMode = responseMode;
app.UseOpenIdConnectAuthentication(options);
}
}
}
我曾尝试编写自定义 openID 身份验证中间件,如文章 Mono with Owin Authentication 。我注意到下面一行抛出了异常 \'由于对象的当前状态,操作无效\'
if (_configuration == null)
{
_configuration = await base.Options.ConfigurationManager.GetConfigurationAsync(base.Context.Request.CallCancelled);
}
OpenID 身份验证和自定义中间件在 Mono Linux 上引发异常
下载声明: 本站所有软件和资料均为软件作者提供或网友推荐发布而来,仅供学习和研究使用,不得用于任何商业用途。如本站不慎侵犯你的版权请联系我,我将及时处理,并撤下相关内容!
下载声明: 本站所有软件和资料均为软件作者提供或网友推荐发布而来,仅供学习和研究使用,不得用于任何商业用途。如本站不慎侵犯你的版权请联系我,我将及时处理,并撤下相关内容!
收藏的用户(0)
X
正在加载信息~