You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 8.0中Session与授权协同工作的配置问题

.NET 8 Session与授权Cookie同步问题解决方案

问题根源

Session和ASP.NET Identity的授权Cookie是两个完全独立的机制:

  • Session由AddSession配置,依赖Session Cookie和分布式缓存,超时由IdleTimeout控制
  • 授权Cookie由ConfigureApplicationCookie配置,超时由ExpireTimeSpan和SlidingExpiration控制

当你把ExpireTimeSpan调大(比如14天)、IdleTimeout保持20分钟时,Session会先过期,但授权Cookie仍有效,导致用户被判定为已登录,但访问Session时因Session不存在而崩溃。

关键修复:调整中间件顺序

你的Program.cs中中间件顺序错误,UseSession必须在UseAuthorization之前执行,否则授权逻辑无法访问Session,且Session初始化不及时。修正后的顺序:

app.UseRouting();

// 先启用Session
app.UseSession();

// 再执行授权
app.UseAuthorization();

app.UseForwardedHeaders(new ForwardedHeadersOptions
{
    ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});

解决方案一:让Session与授权Cookie同步过期

要实现「闲置20分钟自动登出,Cookie默认有效期14天」的需求,需调整两者的配置逻辑,让Session过期时同步失效授权Cookie:

1. 配置基础参数

// Session配置:闲置20分钟过期
builder.Services.AddSession(options =>
{
    options.IdleTimeout = TimeSpan.FromMinutes(20);
    options.Cookie.Name = ".PBP.Session";
    options.Cookie.IsEssential = true;
    // 保持与授权Cookie同域同路径,避免跨域问题
    options.Cookie.Domain = builder.Configuration["CookieDomain"];
    options.Cookie.Path = "/";
});

// 授权Cookie配置:默认14天有效期,滑动过期(用户活动则延长有效期)
builder.Services.ConfigureApplicationCookie(options =>
{
    options.ExpireTimeSpan = TimeSpan.FromDays(14);
    options.LoginPath = "/Identity/Account/Login";
    options.SlidingExpiration = true;
    options.Cookie.Domain = builder.Configuration["CookieDomain"];
    options.Cookie.Path = "/";
});

2. 添加自定义中间件同步过期

在UseSession之后、UseAuthorization之前添加中间件,检查Session有效性,若Session过期则登出用户:

app.UseSession();

// 新增:Session过期时同步登出用户
app.Use(async (context, next) =>
{
    if (context.User.Identity?.IsAuthenticated == true)
    {
        try
        {
            // 尝试读取业务中必须存在的Session键(示例为UserId),触发Session过期检查
            var hasValidSession = context.Session.TryGetValue("UserId", out _);
            if (!hasValidSession)
            {
                await context.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
                context.Response.Redirect("/Identity/Account/Login");
                return;
            }
        }
        catch (InvalidOperationException)
        {
            // Session已从缓存中清除,执行登出
            await context.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
            context.Response.Redirect("/Identity/Account/Login");
            return;
        }
    }
    await next();
});

app.UseAuthorization();

解决方案二:使用ActionFilter全局检查

如果不想用中间件,可创建全局ActionFilter,在所有带[Authorize]特性的Action执行前检查Session:

1. 定义Filter

public class SessionCheckFilter : IAsyncActionFilter
{
    public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        var httpContext = context.HttpContext;
        if (httpContext.User.Identity?.IsAuthenticated == true)
        {
            try
            {
                var hasValidSession = httpContext.Session.TryGetValue("UserId", out _);
                if (!hasValidSession)
                {
                    await httpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
                    httpContext.Response.Redirect("/Identity/Account/Login");
                    return;
                }
            }
            catch (InvalidOperationException)
            {
                await httpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
                httpContext.Response.Redirect("/Identity/Account/Login");
                return;
            }
        }
        await next();
    }
}

2. 注册全局Filter

在Program.cs中添加:

builder.Services.AddControllersWithViews(options =>
{
    options.Filters.Add<SessionCheckFilter>();
});

额外注意事项

  • 若使用分布式缓存(如Redis),需确保Session的缓存配置正确,避免Session提前被清除
  • 不要依赖Session的IsAvailable属性判断过期,需通过尝试读取具体Session键或捕获异常来判断
  • 滑动过期模式下,用户每次活动都会同时延长Session和授权Cookie的有效期

内容的提问来源于stack exchange,提问作者user517406

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.11 22:13:19