【问题标题】:How to make sessions work in IIS with ASP . NET Core?如何使用 ASP 使会话在 IIS 中工作。网络核心?
【发布时间】:2021-01-10 06:20:56
【问题描述】:

我一直在尝试确定是什么导致 Session 值在我的 ASP .NET Core 应用程序中为空,阅读了该站点和 Microsoft Docs 中的大量文档,我认为我要么没有掌握 Sessions 背后的总体思路在 .NET Core 中,或者只是缺少一些东西。 该网页是 .NET Core 3.1,在 IIS Express 中运行甚至部署在我的本地 IIS 上时,一切都运行良好,但是,部署到远程服务器时,会话值似乎不起作用。

(编辑:确切地说,远程服务器中的 Sessions 值行为不稳定,有时它们工作不到一分钟,有时它们根本不起作用)

根据我的阅读,我认为除非我有 IDistributedCache 的某种实现,否则 Sessions 将无法工作,但我没有给自己时间来完全实现这一点,尽管我想到了 SqlServerCache。所以我使用的是微软的默认实现,不推荐用于生产,但无论如何。 Startup.cs文件的相关部分是:

services.AddAuthorization();
        services.AddDistributedMemoryCache();
        services.AddSession(options => {
            options.IdleTimeout = TimeSpan.FromMinutes(60);//You can set Time   
        });

完整的Startup.cs 在这里:

public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllersWithViews();
        services.AddSingleton<IConfiguration>(Configuration);
        services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(options =>
        {
            options.LoginPath = "/Account/Index";
            options.ExpireTimeSpan = TimeSpan.FromHours(24);
            options.Events = new CookieAuthenticationEvents
            {
                OnValidatePrincipal = async contexto =>
                {
                    var accessToken = contexto.Principal.Claims.FirstOrDefault(k => k.Type == "AccessToken");
                    if (accessToken == null || string.IsNullOrWhiteSpace(contexto.Principal.Identity.Name) || !contexto.Principal.Identity.IsAuthenticated)
                    {
                        return;
                    }
                    var userService = contexto.HttpContext.RequestServices.GetRequiredService<IUserService>();
                    var userName = contexto.Principal.Identity.Name;

                    var usuario = await userService.ValidateUser(userName, String.Format("{0}{1}", Configuration.GetSection("ApiPath").Value, "TecaltUser/GetUsers"), (accessToken != null ? accessToken.Value : String.Empty));
                    if (usuario.Item1)
                    {
                        return;
                    }
                    contexto.RejectPrincipal();
                    await contexto.HttpContext.SignOutAsync();
                }
            }; // AGREGAR LA COOKIE AL SERVICIO DE AUTENTICACIÓN
        });
        services.Configure<CookiePolicyOptions>(options =>
        {
            options.CheckConsentNeeded = context => false;
            options.MinimumSameSitePolicy = Microsoft.AspNetCore.Http.SameSiteMode.None;
        });
        services.AddAuthorization();
        services.AddDistributedMemoryCache();
        services.AddSession(options => {
            options.IdleTimeout = TimeSpan.FromMinutes(60);//You can set Time   
        });
        services.AddScoped<IUserService, DALUser>();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
            app.UseHsts();
        }
        app.UseHttpsRedirection();
        app.UseStaticFiles();
        
        app.UseRouting();
        app.UseAuthentication();
        app.UseAuthorization();
        app.UseSession();
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
        });
    }
}

所以我认为我似乎已经探索了大多数选项,例如设置 cookie 的 ExpireTimeSpan,将 CheckConsentNeeded 选项设置为 false,因为我不知道默认情况下它是 true如果用户必须明确同意 cookie,不是吗? 所以我的问题是,在 ASP .NET Core 中设置 Session 真的很难吗?我真的无法判断我的代码中是否有某些内容无法使其正常工作(顺便说一下,cookie 是在从单独的 web api 获取 JWT 后设置的,也在 .NET Core 中)。

向大家致敬,如果有人能帮助我解决我没有考虑的合理甚至明显的事情,我将非常感激

我一直在添加选项,但似乎仍然没有任何效果,我在调用 DistributedMemoryCache 后添加了这些行:

services.Configure<CookiePolicyOptions>(options =>
        {
            options.CheckConsentNeeded = context => true;
            options.MinimumSameSitePolicy = Microsoft.AspNetCore.Http.SameSiteMode.None;
        });
        services.AddSession(options => {
            options.Cookie.IsEssential = true;
            options.IdleTimeout = TimeSpan.FromMinutes(60);//You can set Time   
        });

甚至从 EndPointRouting 更改为 Mvc(我错误地认为它似乎可能有一些相关的东西):

services.AddMvc(options=>
        {
            options.EnableEndpointRouting = false;
        });

最后我调用它们:

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

但是每当我部署到远程服务器时仍然没有结果。说真的,和 Sessions 合作有那么难吗?

【问题讨论】:

  • 我还忘了补充一点,我可以在浏览器中看到会话 Cookie,它们的默认名称为“AspNetCore.Session”和“AspNetCore.Cookies”,但就像我说的那样,它们的值显然是 null
  • 您能告诉我您是如何托管您的应用程序的吗?您是否在服务器中启用负载平衡?
  • @BrandoZhang 我使用 IIS 作为代理和 InProcess 模式托管在 Windows 服务器中。我不认为它是负载平衡的,因为它是一个站点,而不是一个网络农场
  • 虽然同一个文件夹根目录下还有两个站点,一个是API的,但我认为它们没有关系
  • 顺便说一句,是 IIS 10

标签: asp.net-core session iis cookies


【解决方案1】:

正如Brando Zhang 指出的那样,这个问题确实很奇怪。我无法使用 ASP .NET Core 3.1 在该服务器上使用会话。但是,我们最终只使用了身份验证 cookie,并且它以这种方式运行良好,因此它只需要在我们使用会话的地方进行如下小的更改:

public JsonResult AddToCart(int ProductId, int Quantity = 1)
    {
        // GFB CORRECCIÓN SESIÓN NO SE OBTIENE
        //DTOUser User = HttpContext.Session.GetJson<DTOTecalt.Users.DTOUser>("LoadedUser");
        //if (User != null)
        //{
            CartModel Cart = new CartModel();//GetCart();
            List<DTOCart> Lines = new List<DTOCart>();
            
            //DTOUser User = HttpContext.Session.GetJson<DTOTecalt.Users.DTOUser>("LoadedUser");
            int IdUser = 0;
            if(HttpContext.User.Identities.SelectMany(a => a.Claims).FirstOrDefault(r => r.Type == System.Security.Claims.ClaimTypes.NameIdentifier) != null)
            int.TryParse(HttpContext.User.Identities.SelectMany(a => a.Claims).FirstOrDefault(r => r.Type == System.Security.Claims.ClaimTypes.NameIdentifier).Value, out IdUser);
            if (IdUser != 0)
            {
                
                Tuple<string, List<DTOCart>, DTOSummaryCart> _result = new Tuple<string, List<DTOCart>, DTOSummaryCart>(ConstantesWeb.ERROR_PREDET, Lines, new DTOSummaryCart());
                using (DALCart Accion = new DALCart())
                {
                    _result = Accion.GetTotalsCart(IdUser);
                }
                if (!String.IsNullOrEmpty(_result.Item1))
                {
                    return Json(new { ErrorInterno = ConstantesWeb.ERROR_PREDET });
                }
                Lines = _result.Item2;
            }
            else
            {
            return Json(new { Unauthorized = true });
            }

        Cart.AddItem(new DTOCart { ProductItem = new Products.DTOProduct { IdProduct = ProductId } }, Quantity, new DTOUser { IdUser = IdUser });
            List<DTOCart> _resultCart = new List<DTOCart>();
            Tuple<bool, string> AddCart = new Tuple<bool, string>(false, ConstantesWeb.ERROR_PREDET);
            using (DALCart Accion = new DALCart())
            {
                List<DTOCart> Products = Cart.Lines.ToList();
                AddCart = Accion.UpdateCart(Products);
                
            }
            if(!AddCart.Item1)
            {
                return Json(new { ErrorInterno = ConstantesWeb.ERROR_CARRITO_ADD });
            }
            SaveCart(Cart);
            //HttpContext.Session.SetJson("Cart", Cart);
            return Json(new { Exito = true });
        //}
    }

我想发布我们参考的实际解决方案,你可以看到我注释掉了对 HttpContext.Session 的引用

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-02
    • 2020-09-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多