You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 15:12:03