8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

OpenID 身份验证和自定义中间件在 Mono Linux 上引发异常

Andrei Margeloiu 1月前

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);
            }
帖子版权声明 1、本帖标题:OpenID 身份验证和自定义中间件在 Mono Linux 上引发异常
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由Andrei Margeloiu在本站《linux》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 你可以迁移到 .NET 8,或者返回 Windows,或者等待新的维护者采取行动,

返回
作者最近主题: