c# - Web API 请求的滑动 session

标签 c# .net asp.net-mvc session asp.net-web-api2

更新:它似乎正在尝试在 ApplyResponseGrantAsync 中写入新的 cookie header ,但不能,因为它抛出 header 异常已经发送。

更新:更清楚。如何在 Web API 请求期间将 Set-Cookie header 添加到 XHR 响应?

TL;DR; 问题是应用程序使用 MVC 进行身份验证,但大量使用 Web API。 Web API 请求不会滑动 session ,即使它们使用 Authentication 属性 - 几乎可以肯定,因为它是 cookie 响应。

我有一个组合的 MVC 和 Web API 应用程序。大多数情况下,MVC View 仅加载发出大量 Web API 请求的 SPA。 这很好,只是 session 滑动不适用于 Web API 请求。

我可以看到 CookieAuthenticationHandlerApplyResponseGrantAsync 中滑动 session 的位置,但我需要在每个 Web API 请求上强制执行此操作。

model.Properties.IssuedUtc = new DateTimeOffset?(this._renewIssuedUtc);
model.Properties.ExpiresUtc = new DateTimeOffset?(this._renewExpiresUtc);
if (this.Options.SessionStore != null && this._sessionKey != null)
{
  await this.Options.SessionStore.RenewAsync(this._sessionKey, model);
  ClaimsIdentity identity = new ClaimsIdentity((IEnumerable<Claim>) new Claim[1]
  {
    new Claim("Microsoft.Owin.Security.Cookies-SessionId", this._sessionKey)
  }, this.Options.AuthenticationType);
    model = new AuthenticationTicket(identity, (AuthenticationProperties) null);
}
string cookieValue = this.Options.TicketDataFormat.Protect(model);
if (model.Properties.IsPersistent)
  cookieOptions.Expires = new DateTime?(this._renewExpiresUtc.ToUniversalTime().DateTime);
this.Options.CookieManager.AppendResponseCookie(this.Context, this.Options.CookieName, cookieValue, cookieOptions);

有人知道如何强制执行此操作吗?

身份验证设置

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
    LoginPath = new PathString("/Account/Login"),
    Provider = new CookieAuthenticationProvider
    {
        OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
            validateInterval: TimeSpan.FromMinutes(15),
            regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
    },
    SlidingExpiration = true,
    ExpireTimeSpan = TimeSpan.FromMinutes(1)
});

app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5));
app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie);

最佳答案

根据 CookieAuthenticationMiddleware 来源,如果您将 CookieAuthenticationOptionsSlidingExpiration 设置为 true,您的 session 将在每次请求时更新。你可以查看这个code看看你自己。

我想我根据 this line 找到了你的问题为了更新 cookie,SignIn 方法的 AuthenticationPropertiesAllowRefresh 属性应该为真。我猜这是你的问题。

<删除> 如果我没记错的话,您正在使用 `ApplicationSignInManager.SignInAsync()` 来登录您的用户。不幸的是,基于 [implementation][2],无法传递参数来设置 `AllowRefresh`,所以我建议重写 SignInAsync 方法并将 `AllowRefresh` 设置为 true,看看它是否有效。

更新

这是另一种猜测,它可能会解决你的问题。基于this line一个 cookie session 将在其生命周期仅过去 50% 时更新,当我查看代码时,我发现没有办法覆盖它。我建议通过添加一个 Middleware 来更新 cookie 的解决方法,它会在每个请求上 SingIn 用户,因此在每个请求上创建一个新的 cookie,如果如果在 WebAPI 或 MVC 中请求。

app.UseCookieAuthentication之后添加中间件

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
Provider = new CookieAuthenticationProvider
{
    OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
        validateInterval: TimeSpan.FromMinutes(15),
        regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
},
SlidingExpiration = true,
ExpireTimeSpan = TimeSpan.FromMinutes(1)
});

app.Use(async (context, next) =>
{
    var result = await context.Authentication.AuthenticateAsync(DefaultAuthenticationTypes.ApplicationCookie);
    if (result != null)
    {
        result.Properties.ExpiresUtc = null;
        result.Properties.IssuedUtc = null;
        context.Authentication.SignIn(result.Properties, result.Identity);
    }
    await next();
});

基本上,您可以将 SlidingExpiration 设置为 false,因为它与此变通方法无关,而且通过这种方式,CookieAuthentication 上的 OnValidateIdentity 可以不会每 30 分钟重新加载一次用户声明,因为 IssuedUTC 会根据每个请求刷新,如果您需要它,您必须修改此中间件并编写自定义 OnValidateIdentity

关于c# - Web API 请求的滑动 session ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48189866/

相关文章:

c# - 使用 C# 连接并读取 .MDB 项目

c# - 如何在 C# 应用程序中安全地隐藏数据库凭据?

c# - 如何接受函数引用作为参数?

c# - LESS 到 CSS 的转换是在客户端还是在服务器端完成的?

asp.net-mvc - ASP.net MVC 路由参数异常

asp.net - 在 MVC 4.0 中的部分 View 中使用节

C# 无法写入文件 ("being used by another process")?

c# - WPF 工具包 : CheckComboBox and [Flags] enum

.NET、Windows 主机文件、通过代码覆盖 dns

c# - 包 X 与 netcoreapp3.1 不兼容