Stripe结账重定向后Cookie与Session丢失问题咨询
环境
-.NET Core 5
-ASP.NET Core 5 MVC + Web API
-EC2 + Stripe
问题描述
我司基于ASP.NET Core 5 MVC(包含Web API项目及其他类库)构建的Web应用部署在EC2,采用Stripe处理支付。用户进入结账页后,会被重定向至SuccessUrl(支付成功)或CancelUrl(支付取消),这两个地址均指向ASP.NET Core MVC项目,但有时用户会因Session和Cookie丢失而登出。
该问题仅出现在生产环境(API与MVC项目分属不同服务器),测试环境(二者部署在同一服务器)无此问题;且除Edge浏览器外,其余所有浏览器都会出现该问题。我已尝试将SameSite从None改为Lax,但问题仍未解决。
现有Session与Cookie配置代码
services.AddDistributedMemoryCache(); services.AddRazorPages().AddRazorRuntimeCompilation(); services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); services.AddWebBaseContexts(); services.Configure<CookiePolicyOptions>(options => { options.CheckConsentNeeded = context => false; options.MinimumSameSitePolicy = SameSiteMode.Lax; options.Secure = CookieSecurePolicy.Always; }); services.AddHttpClient(); #region "Session init" services.AddDistributedMemoryCache(); services.AddSession(options => { options.Cookie.Name = ".AspNetCore.Session.MakMak.Client"; options.IdleTimeout = TimeSpan.FromDays(150); options.Cookie.IsEssential = true; options.Cookie.SecurePolicy = CookieSecurePolicy.Always; }); #endregion "Session init" services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options => { options.LoginPath = new PathString("/"); } ); app.UseAuthentication(); app.UseSession(); if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); } app.UseStaticFiles(); app.UseCookiePolicy(); // app.UseSession(); app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); }); }
疑问
是否是生产环境的跨服务器部署导致该问题?如何在重定向后保留Session和Cookie?
解答
1. 跨服务器部署是核心诱因
生产环境中API和MVC分属不同服务器,测试环境同服务器,差异点集中在两个关键问题:
- 你当前使用
AddDistributedMemoryCache(),这是单服务器内存级缓存,每个服务器独立维护Session存储,用户请求落到不同服务器时,Session无法共享,直接导致登出。 - Stripe重定向回站点时,若服务器域名/IP不同,浏览器会严格校验Cookie归属,配合现有配置限制,会导致Cookie无法被正确携带。
2. 具体解决步骤
(1)替换分布式Session存储
将内存缓存换成跨服务器共享的存储(如Redis或SQL Server),确保所有服务器访问同一Session数据源:
// 示例:使用Redis作为分布式缓存(需先安装Microsoft.Extensions.Caching.StackExchangeRedis包) services.AddStackExchangeRedisCache(options => { options.Configuration = "你的Redis连接字符串"; options.InstanceName = "MakMakSession:"; }); // 保留原有Session配置,此时Session数据会存储在Redis中实现跨服务器共享 services.AddSession(options => { options.Cookie.Name = ".AspNetCore.Session.MakMak.Client"; options.IdleTimeout = TimeSpan.FromDays(150); options.Cookie.IsEssential = true; options.Cookie.SecurePolicy = CookieSecurePolicy.Always; // 关键:若API和MVC同属一个主域名,设置Cookie的Domain为根域名 options.Cookie.Domain = ".yourdomain.com"; });
(2)优化Cookie配置,确保重定向时可携带
- 统一Cookie Domain:若API和MVC属于同一主域名(如
api.yourdomain.com和www.yourdomain.com),设置Cookie的Domain为根域名.yourdomain.com,实现子域名间Cookie共享。 - 调整SameSite与Secure策略:Stripe重定向属于跨站请求,需匹配HTTPS场景优化配置:
services.Configure<CookiePolicyOptions>(options => { options.CheckConsentNeeded = context => false; options.MinimumSameSitePolicy = SameSiteMode.Lax; options.Secure = CookieSecurePolicy.Always; options.HttpOnly = true; }); // 同步调整认证Cookie配置 services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options => { options.LoginPath = new PathString("/"); options.Cookie.Domain = ".yourdomain.com"; options.Cookie.SameSite = SameSiteMode.Lax; options.Cookie.SecurePolicy = CookieSecurePolicy.Always; options.Cookie.HttpOnly = true; }); - 修正中间件顺序:Session中间件必须在认证中间件之前、Cookie策略中间件之后加载,调整后的顺序如下:
app.UseStaticFiles(); app.UseCookiePolicy(); app.UseSession(); app.UseAuthentication(); app.UseAuthorization(); // 若有授权逻辑需添加 app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); });
(3)验证Stripe重定向URL配置
确保Stripe的SuccessUrl和CancelUrl与用户当前访问的域名一致(均为HTTPS协议的同一主域名),避免跨域导致浏览器拒绝携带Cookie。
3. Edge浏览器无问题的说明
Edge浏览器对跨站Cookie的策略相对宽松,或生产环境中Edge的隐私设置恰好允许Cookie传递;而Chrome、Firefox等浏览器的隐私策略更严格,因此问题仅在非Edge浏览器中显现。
内容的提问来源于stack exchange,提问作者Khaled Helwane

