如何读取 IdentityServer3 上的 ASP.NET 会话? OWIN 管道顺序被打破

How to read ASP.NET Session on IdentityServer3? OWIN Pipeline Order is broken

问题:我正在尝试在 IdentityServer3 控制器 上使用 ASP.NET 会话,但我无法让它工作。

我发现这个类似的 question 解释了如何在 OWIN 中间件上启用会话,并且它工作得很好:我在 IdentityServer 之外创建了一些控制器(也就是说,在“/core”中映射的管道之外) 并且效果很好。我还将 Autofac 添加到我的控制器中,以确保 Autofac(在 IdentityServer 中广泛使用)不是问题,并且它工作正常。

这是工作代码 - Startup.cs:

// register middleware that enables session using SetSessionStateBehavior(SessionStateBehavior.Required)
app.RequireAspNetSession(); 

var config = new HttpConfiguration();
WebApiConfig.Register(config);
app.UseWebApi(config);

var builder = new ContainerBuilder();
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
builder.RegisterType<DummyClassCreatedByAutofac>();;
var container = builder.Build();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);

//app.UseIdentityServer(); // if I add IdentityServer, context.Session is always null

这很好用。中间件 (SetSessionStateBehavior) 运行 在每个请求上都有,会话在构造函数上可用。然而,一旦我将 app.UseIdentityServer() 添加到我的 Startup.cs,IdentityServer 就开始正常工作(并且所有申请都通过会话中间件)但是现在所有控制器的 Session 都是空的 - 不仅对于 IdentityServer 控制器而且对于我的其他控制器(在 IdentityServer 管道之外)- 它们停止工作。

如果我完全删除所有代码并坚持使用常规的 IdentityServer 管道,我只是 找不到在管道中添加 RequireAspNetSession() 的正确位置。 我试过了在许多不同的地方添加,但无法使其工作。

经过反复试验,我意识到会话中间件 RequireAspNetSession() 被以下两个调用破坏了:app.UseEmbeddedFileServer()app.ConfigureCookieAuthentication。当这两个调用都被删除时,Session 对 IdentityServer 控制器可用(并且也对我的其他控制器再次可用)。问题可能是因为某些 OWIN 中间件 运行 在特定 stages 上(使用 UseStageMarker 并定义 PipelineStage),并且可能我打破了中间件。 UseEmbeddedFileServer 例如 运行s on stage PipelineStage.MapHandler, 以及 RequireAspNetSession.

我尝试在这些中间件之前和之后添加 app.RequireAspNetSession(),但它也不起作用。事实上,app.RequireAspNetSession() 在 Map() 方法内部使用时永远不会工作,这是配置这些中间件的地方(在 UseIdentityServer() 内部):

app.Map("/core", coreApp =>
{
  // this DOESN'T work, even if I remove
  // UseEmbeddedFileServer() or ConfigureCookieAuthentication()
  coreApp.RequireAspNetSession(); 
  //...
  coreApp.UseIdentityServer(idsrvOptions); 
}

_

// this WORKS as long as inside the Map() I don't call 
// UseEmbeddedFileServer() or ConfigureCookieAuthentication() 
app.RequireAspNetSession(); 
app.Map("/core", coreApp =>
{
  //...
  coreApp.UseIdentityServer(idsrvOptions);
}

最后,如果我不使用 Map 方法(并直接在根文件夹上设置 IdentityServer API),它工作正常(会话对所有控制器可用,即使我保留 UseEmbeddedFileServer( ) 和 ConfigureCookieAuthentication() 中间件)。但这是不可接受的,因为我需要在映射文件夹上 运行 APIs。

总结:如果我在 Map() 中使用 RequireAspNetSession(),它不起作用(会话始终为空)。如果我在 Map() 外部使用 RequireAspNetSession() 但在 Map() 内部保留 UseEmbeddedFileServer() 或 ConfigureCookieAuthentication(),它也不起作用。

如何使 RequireAspNetSession() 在 IdentityServer3 管道中工作?

此外,Map("/core") 如何影响(并破坏)托管在该管道外部的 DefaultController 管道?

没坏。这是设计使然。 IdentityServer 故意清除会话。

你有几个选择。

1) 您可以创建一个 cookie 助手
2) SignInMessage 包含大部分你需要的东西 -> 不要忘记 LoginViewModel

您的用户或应用程序登录后,会话将再次由您控制。