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

.NET Core 3.1应用登出后旧Cookie仍可访问API的解决需求

解决.NET Core 3.1中登出后旧Cookie仍可访问API的问题

我在.NET Core 3.1应用中遇到如下场景:用户登录后从本地存储获取Cookie,执行登出操作后,使用该Cookie通过Postman仍能访问API,需要阻止这种情况发生。

当前Startup配置代码

options.Events = new CookieAuthenticationEvents
{
    OnValidatePrincipal = SecurityStampValidator.ValidatePrincipalAsync
};

当前登出逻辑代码

var authenticationName = HttpContext.User?.Identity?.Name;

var user = await userManager.FindByNameAsync(authenticationName);
if (user != null)
{
    await userManager.UpdateSecurityStampAsync(user);
    await userManager.UpdateAsync(user);
}

await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme)

修复方案

1. 调整SecurityStamp验证间隔

SecurityStampValidator.ValidatePrincipalAsync默认30分钟才会验证一次SecurityStamp,导致登出后更新了Stamp,旧Cookie仍能在30分钟内正常访问。可以缩短验证间隔,确保Stamp变更后快速生效:

在Startup中添加配置:

services.Configure<SecurityStampValidatorOptions>(options =>
{
    // 设置为10秒验证一次,可根据业务需求调整
    options.ValidationInterval = TimeSpan.FromSeconds(10);
});

2. 确保登出时彻底清除Cookie

SignOutAsync理论上会清除认证Cookie,但部分场景下可能因配置异常失效,可以手动强制删除Cookie:

// 执行登出操作
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
// 手动删除Cookie确保彻底清除
Response.Cookies.Delete(CookieAuthenticationDefaults.CookiePrefix + CookieAuthenticationDefaults.AuthenticationScheme);

3. 移除冗余的UpdateAsync调用

UpdateSecurityStampAsync方法内部已经会调用UpdateAsync更新用户数据,登出代码里的await userManager.UpdateAsync(user);属于冗余操作,直接删除即可,优化后代码:

var authenticationName = HttpContext.User?.Identity?.Name;
var user = await userManager.FindByNameAsync(authenticationName);
if (user != null)
{
    await userManager.UpdateSecurityStampAsync(user);
}
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);

4. 强制每次请求验证Principal(可选)

如果需要更高的安全性,可以自定义OnValidatePrincipal事件,强制每次请求都验证SecurityStamp:

options.Events.OnValidatePrincipal = async context =>
{
    var userManager = context.HttpContext.RequestServices.GetRequiredService<IUserManager<IdentityUser>>();
    var user = await userManager.GetUserAsync(context.Principal);
    if (user != null)
    {
        var isValid = await userManager.VerifyUserTokenAsync(
            user, 
            TokenOptions.DefaultProvider, 
            "SecurityStamp", 
            context.Properties.GetTokenValue("SecurityStamp"));
        
        if (!isValid)
        {
            context.RejectPrincipal();
            await context.HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
        }
    }
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 07:32:56