如何防止每次请求都重置Session.Id?

时间:2019-06-24 16:00:53

标签: c# session asp.net-core-2.2

我已经完成了dotnet core 2.2的会话配置,但是仍然会为每个包含Session.Id的请求创建一个新会话。 因此,我不能将会话用作数据持有人。

我想将会话与ShoppingCart结合使用。

为此,我创建了一个单独的API项目,一个单独的Service项目和一个SPA项目。

这是ConfigureServices方法

public void ConfigureServices(IServiceCollection services)
        {
            services.AddAutoMapper();
            // DbContext using SQL Server Provider
            services.AddDbContext<ICleanTasteDbContext, CleanTasteDbContext>(options =>
            {
                options.UseSqlServer(
                    Configuration.GetConnectionString("TasteConnection"),
                    m => m.MigrationsAssembly("Taste.Persistence")
                );
            });
            services.Configure<CookiePolicyOptions>(options =>
            {
                options.CheckConsentNeeded = context => false;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });
            services.AddDistributedMemoryCache();
            services.AddSession(options =>
            {
                options.IdleTimeout = TimeSpan.FromMinutes(30);
                options.Cookie.IsEssential = true;
                options.Cookie.HttpOnly = true;
            });
            services.AddHttpContextAccessor();

            // custome services
            services.AddTransient<ICartService<ICart>, CartService>();

            // MVC            
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
            // Cors
            services.AddCors();

            services.AddSpaStaticFiles(config =>
            {
                config.RootPath = "wwwroot";
            });
        }

这是Configure方法

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseDatabaseErrorPage();
            }
            else
            {
                app.UseHsts();
            }

            app.UseCors(x =>
                    x.AllowAnyHeader()
                    .AllowAnyMethod()
                    .AllowAnyOrigin()
                    .AllowCredentials()
                    );
            app.UseAuthentication();
            app.UseDefaultFiles();
            app.UseStaticFiles();
            app.UseCookiePolicy();
            app.UseSession();
            app.UseMvc(routes =>
            {
                routes.MapSpaFallbackRoute(
                    name: "spa-fallback",
                    defaults: new { controller = "fallback", action = "index" }
                );
            });

            app.UseSpa(spa =>
            {
                if (env.IsDevelopment())
                {
                    spa.UseProxyToSpaDevelopmentServer("http://localhost:4200");
                }
            });
        }

在CartsController中,该服务的调用方式如下

var cart = await cartService.Add(product);
在CartService类IHttpContextAccessor中

注入并如下调用

var cart = await httpContext.HttpContext.Session.Get<CartModel>(SESSION_NAME);
httpContext.HttpContext.Session.Set<CartModel>(SESSION_NAME, cart);

设置正确,但是在下一个请求中,有一个会话的新实例,并且再次为空。

我在做什么错了?

这与我使用不同的项目有关吗?

1 个答案:

答案 0 :(得分:0)

很难说,但是有两个潜在的问题:

  1. 您正在使用内存中的会话,这意味着您受进程限制。会话永远不会在两个不同的项目之间共享,因为每个项目都是一个独立的运行进程,具有自己的内存支持。此外,当应用程序停止运行时,存储在内存中的所有内容都将随之消失,因此,例如,如果停止并重新启动调试,甚至只是重新构建调试程序,会话都会再见。没有真正的“分布式”内存缓存。这只是使用内存的IDistributedCache的实现,但不是真正分布式的。

  2. 即使您拥有真正分布的会话存储,默认情况下,每个应用程序也会在其中占据自己的位置,这意味着仍不会共享。您需要确保两个应用程序都使用相同的数据保护密钥环位置,并且两个应用程序都设置了相同的应用程序名称。