我是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时为null。 HttpContext.Current属性不是。 Sessions + OWIN有任何限制吗?这个问题有解决方法吗?应该如何接近它?
旁注1: 我试图添加我在其中一个SO问题中找到的这段代码,而Session仍然是null:
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(作为空方法)。那也没有用。
我欢迎任何建议。 谢谢!
答案 0 :(得分:10)
你几乎那里。 您的会话仍然为空的原因是您没有指示OWIN在您的中间件执行之前初始化System.Web Sessions。
通过在中间件注册后添加 .UseStageMarker(..) ,您将告诉OWIN执行pipline应该在哪里执行 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 Middleware在最后一个事件(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对中间件的工作方式有一个excellent article。 有关Asp.net中执行顺序的详细信息,请参阅PiplineStage enum文档和HttpApplication文档。