Asp.net

HttpContext.Current.Session 為 null + OWIN

  • May 12, 2017

我對 OWIN 完全陌生,這個問題一直是我的主要障礙。

基本上,在我的 MVC 應用程序中,我在 Startup 類中有以下內容:

public partial class Startup
{
   public void ConfigureAuth(IAppBuilder app)
   {
       app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
       app.UseCookieAuthentication(new CookieAuthenticationOptions());
       app.UseOpenIdConnectAuthentication(
               new OpenIdConnectAuthenticationOptions
               {
                   ClientId = OfficeSettings.ClientId,
                   Authority = OfficeSettings.Authority,

                   TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters()
                   {
                       RoleClaimType = "roles"
                   },

                   Notifications = new OpenIdConnectAuthenticationNotifications()
                   {

                   AuthorizationCodeReceived = (context) =>
                       {
                       // code hidden for readability

                           if(HttpContext.Current.Session == null)
                           {
                               // It's null. Why is that?
                           }

                           var session = HttpContext.Current.Session;
                           if (session["myMockSession"] != null)
                           {
                               // Do stuff...
                           }
                       },

                       RedirectToIdentityProvider = (context) =>
                       {
                           // code hidden for readability
                       },

                       AuthenticationFailed = (context) =>
                       {
                           // code hidden for readability
                       }
                   }
               });

我不明白為什麼在調試時 Session 為空。HttpContext.Current 屬性不是。Sessions + OWIN 有什麼限制嗎?這個問題有什麼解決方法嗎?應該如何處理它?

旁注 1:我嘗試添加在 SO 問題之一中找到的這段程式碼,但 Session 仍然為空:

app.Use((context, next) =>
           {
               // Depending on the handler the request gets mapped to, session might not be enabled. Force it on.
               HttpContextBase httpContext = context.Get<HttpContextBase>(typeof(HttpContextBase).FullName);
               httpContext.SetSessionStateBehavior(SessionStateBehavior.Required);
               return next();
           });

旁注 2:我似乎再也找不到它了,但是有人在 SO 問題之一中建議在 Global.asax 中添加空方法 Session_Start 和 Session_End (作為空方法)。那也沒有用。

我歡迎任何建議。謝謝!

你快到。您的會話仍然為空的原因是您沒有指示 OWIN 在執行中間件之前初始化 System.Web 會話。

通過在中間件註冊後添加*.UseStageMarker(..)* 您將告訴 OWIN 在執行管道中的哪個位置執行SetSessionStateBehaviour

app.Use((context, next) =>
{
   var httpContext = context.Get<HttpContextBase>(typeof(HttpContextBase).FullName);
   httpContext.SetSessionStateBehavior(SessionStateBehavior.Required);
   return next();
});

// To make sure the above `Use` is in the correct position:
app.UseStageMarker(PipelineStage.MapHandler);

預設情況下,Owin 中間件在最後一個事件 (PipelineStage.PreHandlerExecute) 處執行,在這種情況下這對您來說太晚了。

現在,要使用會話,您需要在第二個中間件中工作,該中間件在 Asp.Net 執行時獲取會話**之後執行。**此中間件必須在PostAquireState階段執行,如下所示:

.Use((context, next) =>
{
    // now use the session
    HttpContext.Current.Session["test"] = 1;

    return next();
})
.UseStageMarker(PipelineStage.PostAcquireState);

Asp.Net katana docs 有一篇關於中間件如何工作的優秀文章。有關 Asp.net 中執行順序的詳細資訊,請參閱PiplineStage列舉文件和HttpApplication文件。

引用自:https://stackoverflow.com/questions/37920879