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

用户登出后如何使AspNetCore.Identity.Application Cookie失效

问题根因

ASP.NET Core Identity 默认使用无状态的Cookie认证机制:加密后的完整认证票据直接存储在客户端Cookie中,服务端默认不会留存已生效票据的校验记录。只要Cookie本身未超出有效期、签名验证通过,服务端就会判定为合法请求,因此用户登出后即使删除了本地Cookie,提前复制的旧有效Cookie仍然可以正常通过身份校验。

解决方案

方案1:接入服务端票据存储(最彻底,推荐)

将完整认证票据存储在服务端(支持内存、Redis、数据库等存储介质),客户端Cookie仅留存票据唯一标识,登出时直接删除服务端对应的票据,即可让旧Cookie完全失效。
实现步骤如下:

  1. 实现自定义ITicketStore,以下是基于分布式缓存的实现示例:
public class DistributedCacheTicketStore : ITicketStore
{
    private readonly IDistributedCache _cache;
    private const string KeyPrefix = "AuthTicket_";

    public DistributedCacheTicketStore(IDistributedCache cache)
    {
        _cache = cache;
    }

    public async Task<string> StoreAsync(AuthenticationTicket ticket)
    {
        var key = KeyPrefix + Guid.NewGuid().ToString("N");
        await SaveTicketToCache(key, ticket);
        return key;
    }

    public async Task RenewAsync(string key, AuthenticationTicket ticket)
    {
        await SaveTicketToCache(key, ticket);
    }

    public async Task<AuthenticationTicket> RetrieveAsync(string key)
    {
        var ticketBytes = await _cache.GetAsync(key);
        return ticketBytes == null ? null : TicketSerializer.Default.Deserialize(ticketBytes);
    }

    public async Task RemoveAsync(string key)
    {
        await _cache.RemoveAsync(key);
    }

    private async Task SaveTicketToCache(string key, AuthenticationTicket ticket)
    {
        var cacheOptions = new DistributedCacheEntryOptions();
        if (ticket.Properties.ExpiresUtc.HasValue)
        {
            cacheOptions.AbsoluteExpiration = ticket.Properties.ExpiresUtc.Value;
        }
        await _cache.SetAsync(key, TicketSerializer.Default.Serialize(ticket), cacheOptions);
    }
}
  1. 在Program.cs中注册服务,替换默认的客户端票据存储逻辑:
// 注册分布式缓存,测试可先用内存缓存,生产环境建议替换为Redis
builder.Services.AddDistributedMemoryCache();
// 注册自定义票据存储
builder.Services.AddScoped<ITicketStore, DistributedCacheTicketStore>();

// 配置Identity Cookie使用服务端票据存储
builder.Services.AddAuthentication(options =>
{
    options.DefaultScheme = IdentityConstants.ApplicationScheme;
})
.AddIdentityCookies(options =>
{
    options.ApplicationCookie.Configure(cookieOpt =>
    {
        cookieOpt.SessionStore = builder.Services.BuildServiceProvider().GetRequiredService<ITicketStore>();
    });
});
  1. 原有登出逻辑无需修改,SignOutAsync方法会自动调用ITicketStore.RemoveAsync删除服务端对应的票据,旧Cookie即使被复用也无法在服务端找到匹配的票据,直接会被判定为未登录。

方案2:添加Cookie动态校验逻辑(轻量实现)

通过配置Cookie的OnValidatePrincipal验证事件,每次请求校验Cookie的有效性,比如维护已登出票据的黑名单,校验时直接拒绝黑名单内的Cookie:

builder.Services.ConfigureApplicationCookie(opt =>
{
    opt.Events = new CookieAuthenticationEvents
    {
        OnValidatePrincipal = async context =>
        {
            var userId = context.Principal?.FindFirstValue(ClaimTypes.NameIdentifier);
            if (string.IsNullOrEmpty(userId))
            {
                context.RejectPrincipal();
                return;
            }
            // 登录时可给AuthenticationTicket添加唯一票据ID,存在Properties中
            var ticketId = context.Properties.Items.TryGetValue("TicketId", out var id) ? id : string.Empty;
            if (string.IsNullOrEmpty(ticketId)) return;
            
            var cache = context.HttpContext.RequestServices.GetRequiredService<IDistributedCache>();
            // 登出时将对应TicketId存入黑名单缓存,缓存有效期和Cookie有效期一致即可
            var isInvalid = await cache.GetStringAsync($"InvalidTicket:{ticketId}");
            if (!string.IsNullOrEmpty(isInvalid))
            {
                context.RejectPrincipal();
                await context.HttpContext.SignOutAsync(IdentityConstants.ApplicationScheme);
            }
        }
    };
});

辅助优化

可以配合缩短Cookie有效期,降低旧Cookie的可用时间窗口:

builder.Services.ConfigureApplicationCookie(opt =>
{
    opt.ExpireTimeSpan = TimeSpan.FromHours(2); // 配置Cookie绝对有效期为2小时
    opt.SlidingExpiration = true; // 开启滑动过期,活跃用户操作时自动续期
});

内容的提问来源于stack exchange,提问作者Niranga

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 22:45:03