OWIN 中间件可以使用 http 会话吗?

Posted

技术标签:

【中文标题】OWIN 中间件可以使用 http 会话吗?【英文标题】:Can OWIN middleware use the http session? 【发布时间】:2014-06-27 05:57:57 【问题描述】:

我为 ASP.NET 和 SignalR 复制了一些代码,我决定将其重写为 OWIN 中间件以删除此重复。

一旦我运行它,我注意到HttpContext.Current.Session 为空,并且我没有在我的中间件拥有的IOwinContext 上看到任何会话对象。

是否可以从 OWIN 访问 http 会话?

【问题讨论】:

【参考方案1】:

是的,但它是一个相当黑客。它也不适用于 SignalR,因为 SignalR 必须在获取会话之前运行以防止长时间的会话锁定。

这样做可以为任何请求启用会话:

public static class AspNetSessionExtensions

    public static IAppBuilder RequireAspNetSession(this IAppBuilder app)
    
        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();
        );
        // SetSessionStateBehavior must be called before AcquireState
        app.UseStageMarker(PipelineStage.MapHandler);
        return app;
    

然后您可以使用HttpContext.Current.Session

访问会话
HttpContextBase httpContext = context.Get<HttpContextBase>(typeof(HttpContextBase).FullName);

【讨论】:

我的会话仍然为空。是什么原因造成的? 这里还是null!! @Rastko 也许这个会话黑客可以在 IIS 上与 OWIN 一起使用,但不能与自托管 OWIN 一起使用。你用的是哪个? 正确,selfhost中没有会话。 会话在AcquireState 阶段初始化。在此阶段之前运行的任何 Owin 中间件,例如通过使用app.UseStageMarker 将遇到会话为空,无论此修复如何。【参考方案2】:

这个答案是来自the initial answer 的混音,所以它的要点应该归功于@Tratcher。尽管单独发布它而不是建议编辑,但它已经足够不同了。


假设您想为基本测试目的制作一个小型 OWIN 应用程序(例如,在进行集成测试时作为更大 API 的存根/伪造),包括使用会话状态的稍微有点不自然的方式就可以了。

首先,你需要这些:

using Microsoft.Owin;
using Microsoft.Owin.Extensions;
using Owin;

通过这些你可以创建一个辅助方法:

public static void RequireAspNetSession(IAppBuilder app)

    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);

您也可以像原始答案一样将其创建为扩展方法。

请注意,如果您不使用UseStageMarker,您会遇到此错误:

“/”应用程序中的服务器错误。 'HttpContext.SetSessionStateBehavior' 只能在引发 'HttpApplication.AcquireRequestState' 事件之前调用。

无论如何,通过上述方法,您现在可以像这样在您的 OWIN 应用程序中使用 HttpContext:

public void Configuration(IAppBuilder app)

    RequireAspNetSession(app);

    app.Run(async context =>
    
        if (context.Request.Uri.AbsolutePath.EndsWith("write"))
        
            HttpContext.Current.Session["data"] = DateTime.Now.ToString();
            await context.Response.WriteAsync("Wrote to session state!");
        
        else
        
            var data = (HttpContext.Current.Session["data"] ?? "No data in session state yet.").ToString();
            await context.Response.WriteAsync(data);
        
    );

如果您使用这个小应用启动 IIS Express,您将首先获得:

会话状态中还没有数据。

那么如果你去http://localhost:12345/write你会得到:

写入会话状态!

然后,如果您返回/转到该主机上的任何其他网址,您将获得:

2015 年 11 月 4 日上午 10:28:22

或类似的东西。

【讨论】:

System.Web.HttpContext.Current.SessionOnResponseSignIn 方法中为空。代码:Provider = new CookieAuthenticationProvider() OnResponseSignIn = async context =&gt;【参考方案3】:

这是一个旧的问答,但没有一个答案是完整的,所以我想我会分享我发现的 here。这对我很有用!

首先,我必须安装 Owin.Extensions。那么……

你快到了。您的会话仍然为空的原因是您 之前没有指示 OWIN 初始化 System.Web 会话 你的中间件正在被执行。

通过在中间件注册后添加 .UseStageMarker(..) 你会告诉 OWIN 它应该在执行管道中的哪个位置执行 设置会话状态行为。

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 有一篇关于如何中间件的优秀文章 作品。请参阅 PiplineStage 枚举文档和 HttpApplication 文档 在 Asp.net 中执行顺序的详细信息。

【讨论】:

以上是关于OWIN 中间件可以使用 http 会话吗?的主要内容,如果未能解决你的问题,请参考以下文章

OWIN 中间件中的全局异常处理

在我自己的 OWIN 中间件中使用 Ninject DI

使用 Ninject OWIN 中间件在 OWIN 启动中注入 UserStore

OWIN 身份验证管道正确使用 Katana 中间件?

支持 JWT 密钥轮换的承载令牌认证的 Owin 中间件

使用Owin中间件搭建OAuth2.0认证授权服务器