.NET 6 Web API中Cookie未过期却10分钟后失效问题求助
问题描述
我在项目中使用Cookie实现用户认证,编写了Login方法用于校验用户是否已认证。该方法在本地localhost环境运行正常,但部署到线上环境后,仅10分钟就返回NotAuthenticated。我已经将Cookie过期时间修改为30天,问题仍未解决。相关代码及Program.cs配置如下:
校验认证状态的Login方法
public async Task<IActionResult> Login() { try { if (!_httpContextAccessor.HttpContext.User.Identity.IsAuthenticated) { return Ok(new ResponseDto { IsSuccessFull = false, Message = ErrorsMessages.NotAuthenticated, Status = "NotAuthenticated" }); } var claims = User.Identities.First().Claims.ToList(); var user = claims?.FirstOrDefault(x => x.Type.Equals(ClaimTypes.MobilePhone, StringComparison.OrdinalIgnoreCase))?.Value; var result = await _userRepository.GetUserAllDetailsByMobileAsync(user); return Ok(new ListResponseDto<GetUserWithReservationDto> { IsSuccessFull = true, Data = result, Message = ErrorsMessages.Authenticated, Status = "Authenticated" }); } catch (Exception ex) { _logger.LogError(ex, "An error occurred while processing the request."); return StatusCode(StatusCodes.Status500InternalServerError, new ListResponseDto<Exception> { IsSuccessFull = false, Data = ex, Message = "An error occurred.", Status = "Error" }); } }
Program.cs配置代码
using FluentValidation.AspNetCore; using Lakoode.Models.Context; using Lakoode.Repository.GenericRepository; using Lakoode.Repository.Implementation.Account; using Lakoode.Repository.Implementation.Reservation; using Lakoode.Repository.Implementation.Villa; using Lakoode.Repository.Interfaces.Account; using Lakoode.Repository.Interfaces.Reservation; using Lakoode.Repository.Interfaces.Villa; using Lakoode.Utilities.SmsSender; using Lakoode.Utilities.Utiliteis; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.EntityFrameworkCore; using Microsoft.OpenApi.Models; using Microsoft.Extensions.Logging; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; var builder = WebApplication.CreateBuilder(args); builder.Services.AddDbContext<LakoodeDbContext>( options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")) ); builder.Services.AddCors(c => { c.AddPolicy("AllowOrigin", options => options.WithOrigins("https://lakoode.ir") .AllowAnyMethod() .AllowAnyHeader() .AllowCredentials()); }); builder.Services.AddControllers() .AddFluentValidation(options => { options.ImplicitlyValidateChildProperties = true; options.ImplicitlyValidateRootCollectionElements = true; options.RegisterValidatorsFromAssembly(System.Reflection.Assembly.GetExecutingAssembly()); } ) .AddJsonOptions(options => options.JsonSerializerOptions.WriteIndented = true); builder.Services.AddAuthentication(options => { options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; }).AddCookie(options => { options.LoginPath = "/account/Login"; options.LogoutPath = "/SignOut"; options.ExpireTimeSpan = TimeSpan.FromDays(7); options.SlidingExpiration = true; options.Cookie.SameSite = SameSiteMode.None; options.Cookie.SecurePolicy = CookieSecurePolicy.Always; }); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "Lakoode Service", Version = "v1" }); }); builder.Services.AddScoped(typeof(IRepository<>), typeof(Repository<>)); builder.Services.AddScoped<IUserRepository, UserRepository>(); builder.Services.AddScoped<ISmsSender, SmsSender>(); builder.Services.AddScoped<IVillaRepsoitory, VillaRepsoitory>(); builder.Services.AddScoped<IReservationRepository, ReservationRepository>(); builder.Services.AddAutoMapper(typeof(Program)); var app = builder.Build(); app.UseRouting(); app.UseCors("AllowOrigin"); app.UseAuthentication(); app.UseAuthorization(); app.UseDeveloperExceptionPage(); app.UseSwagger(); app.UseSwaggerUI(); app.UseHttpsRedirection(); app.MapControllers(); app.Run();
问题排查与解决方案
结合线上环境特性,问题大概率不是代码里的ExpireTimeSpan配置导致,以下是几个核心排查方向:
1. 服务器会话超时配置
线上服务器(如IIS、Nginx)的独立超时设置会覆盖代码中的Cookie过期规则:
- IIS:检查应用程序池的「空闲超时」(默认20分钟),若超过时间无请求,应用池会回收,导致会话数据丢失。建议将空闲超时调整为与Cookie过期时间匹配,或设为0(不超时)。
- Nginx:若用反向代理,检查
proxy_read_timeout等配置,避免提前终止会话。
2. 补充Cookie的MaxAge属性
代码仅设置ExpireTimeSpan,未显式配置options.Cookie.MaxAge,部分浏览器对仅设置Expires的Cookie处理逻辑不一致。补充配置:
options.Cookie.MaxAge = TimeSpan.FromDays(30);
3. 负载均衡环境的会话一致性
若线上用多台服务器负载均衡,需确保会话数据跨服务器共享:
- 配置分布式缓存(如Redis)存储会话数据,替换默认内存缓存。在Program.cs中添加:
并在builder.Services.AddStackExchangeRedisCache(options => { options.Configuration = builder.Configuration.GetConnectionString("Redis"); }); builder.Services.AddSession(options => { options.IdleTimeout = TimeSpan.FromDays(30); options.Cookie.HttpOnly = true; options.Cookie.IsEssential = true; });app.Run()前添加app.UseSession();(注意顺序要在UseAuthentication之前)。
4. 浏览器Cookie策略限制
- 确认线上环境为HTTPS(代码已设
CookieSecurePolicy.Always,必须确保网站是HTTPS,否则浏览器会拒绝保存Secure Cookie)。 - 若前端与API域名不同,检查浏览器第三方Cookie阻止设置,同时配置Cookie的
Domain属性:options.Cookie.Domain = ".lakoode.ir"; // 适配子域名场景
5. 滑动过期的生效问题
开启SlidingExpiration = true后,需确保用户在会话有效期内有活跃请求,否则Cookie会按时过期。另外,线上服务器时间不一致也可能导致滑动过期失效,建议同步服务器系统时间。
内容的提问来源于stack exchange,提问作者ari23yan
相关产品推荐
相关产品推荐

