ASP.NET Core:会话 ID 总是更改

5
今天开始了一个全新的ASP.NET Core网站。按照说明添加了会话(sessions)。我们在首页上打印出Session ID,它总是唯一的。
我认为可能是cookie合规性问题,所以我在Chrome的高级设置和调试器中清除了所有cookie。但是横幅没有重新出现让我接受。
我还尝试简单地禁用CheckConsentNeeded,但也没有影响。
基本上,这是来自默认项目加上MSDN的重复内容,只是根据上面描述进行了微调。
    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDistributedMemoryCache();

        services.AddSession(options =>
        {
            // Set a short timeout for easy testing.
            options.IdleTimeout = TimeSpan.FromSeconds(10);
            options.Cookie.HttpOnly = true;
            //options.Cookie.SecurePolicy = CookieSecurePolicy.Always; //require https
            // Make the session cookie essential
            options.Cookie.IsEssential = true;
        });

        services.Configure<CookiePolicyOptions>(options =>
        {
            // This lambda determines whether user consent for non-essential cookies is needed for a given request.
            options.CheckConsentNeeded = context => false; //true;
            options.MinimumSameSitePolicy = SameSiteMode.None;
        });


        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseCookiePolicy();
        app.UseSession();

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
    }

6
只有在您实际存储某些内容之前,会话 ID 才会更改,之后 ID 就固定不变了。 - Wiktor Zychla
你说得对!这让我想到了更多的问题。首先,为什么要设计成那样?其次,更重要的是对于我的进展,我们肯定不希望在每个控制器端点都要确保会话设置正确;有没有一种正常的方法来确认/初始化会话?在旧版ASP.NET中,我们使用属性,但我还没有学习如何升级。 - Zoop
ASP.NET Core仍然使用属性(假设您正在谈论像AuthorizeAttribute,AllowAnonymousAttribute等这样的东西)。例如,我有一个自定义的ActionFilterAttribute,我用它来装饰大多数控制器,并检查我的自定义主体是否具有特定声明 - 您可以使用会话值执行类似的操作。 - Tieson T.
3个回答

13

Wiktor Zychla在第一个评论中是正确的:您必须分配任何数据给ID以保持其粘性。

我只是在我的控制器中为会话分配了任意数据:

        public IActionResult Index()
        {
            HttpContext.Session.Set("What", new byte[] { 1, 2, 3, 4, 5 });
        }

之后,HttpContext.Session.Id并没有改变,这是可以预料的。

作为我从ASP.NET Framework进入ASP.NET Core的第一次尝试,我并没有预料到这一点,相信我不会是最后一个这样的人!


这似乎可以工作,但是我必须在每个控制器的每个IActionResult方法中包含此代码...看起来非常笨拙。 - Bob Kaufman
2
正确,我的答案不是“最佳实践”答案。它是一个“这是你需要获得预期行为的最低要求”答案。 - Zoop

1
Zoop的回答给了我灵感,但正如我的评论所示,如果您的应用程序有很多操作,它会变得混乱。基于他们的答案,我想出了以下解决方案:
如果您还没有一个应用程序的基本控制器,请创建一个。从该控制器派生所有现有的控制器。覆盖行为类似于ASP.NET中旧的Page_Load的基本方法。OnActionExecuting在任何操作代码之前被调用。
public class MyApplicationController : Controller
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        base.OnActionExecuting(filterContext);
        HttpContext.Session.Set("What", new byte[] { 1, 2, 3, 4, 5 });
    }
}

编辑:这也是一个不完美的解决方案。我已经放弃在我的MVC项目中尝试使用Session。这将适用于您除了GETPOST之外什么都不做的情况。(例如,$ajax会搞砸它。)


0
关于这个问题。
你的会话 ID 是根据客户端的 Cookie 来确定的。 你可以在 Chrome Devtool 中检查该值。
默认的键是 .AspNetCore.Session。

enter image description here

如果你的.AspNetCore.Session或Cookie为空,服务器会自动创建一个新的会话ID。
所以,首先检查你的请求头。
在最后一个图像中,你可以看到HostOrigin不同,由于CORS问题,默认情况下请求将不包括Cookie
你可以在请求中添加withCredentials标头来解决这个问题。
axios中,你可以这样做:
const instance = axios.create({
   withCredentials: true,
   baseURL: BASE_URL
})
instance.get('/todos')

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接