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

ASP.NET Core中如何将JWT安全存储到Cookie中

ASP.NET Core 实现JWT存储到Cookie的落地方法

你现有的JWT基础认证配置不需要重构,只需要补全「从Cookie读取令牌的适配逻辑」和「令牌签发后写入安全Cookie」两个核心环节即可,具体步骤如下:

1. 调整JWT Bearer配置,支持从Cookie提取令牌

默认JWT Bearer中间件只会从请求头Authorization: Bearer <token>位置读取令牌,你需要给JWT事件增加读取Cookie的逻辑,修改后的配置代码如下:

services.AddControllers();
services.AddTransient<IUserRepository, UserRepository>();
services.AddTransient<ITokenService, TokenService>();
IdentityModelEventSource.ShowPII = true;
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ValidIssuer = Configuration["Jwt:Issuer"],
            ValidAudience = Configuration["Jwt:Issuer"],
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"]))
        };
        // 新增:从指定Cookie读取JWT
        options.Events = new JwtBearerEvents
        {
            OnMessageReceived = context =>
            {
                // Cookie名可自定义,示例用AccessToken作为标识
                if (context.Request.Cookies.TryGetValue("AccessToken", out var token) && !string.IsNullOrEmpty(token))
                {
                    context.Token = token;
                }
                return Task.CompletedTask;
            }
        };
    });

记得在Configure方法中保持中间件顺序正确:app.UseAuthentication()必须放在app.UseAuthorization()、app.MapControllers()之前,否则认证逻辑不会生效。

2. 登录签发JWT时写入安全属性Cookie

原来的登录逻辑中,签发完JWT不需要将令牌返回到响应体给前端存储,直接通过响应写入Cookie即可,必须配置安全属性规避常见Web攻击:

[HttpPost("login")]
public async Task<IActionResult> Login([FromBody] LoginDto dto)
{
    // 原有账号密码校验逻辑不变
    var isValidUser = await _userRepository.CheckPasswordAsync(dto.Username, dto.Password);
    if (!isValidUser) return Unauthorized("账号或密码错误");

    var user = await _userRepository.GetUserByNameAsync(dto.Username);
    // 调用现有TokenService生成JWT字符串
    var jwtToken = _tokenService.GenerateJwt(user);

    // 配置Cookie安全规则
    var cookieOpt = new CookieOptions
    {
        HttpOnly = true, // 禁止前端JS读取Cookie,从根源避免XSS窃取令牌
        Secure = true, // 仅允许HTTPS协议传输Cookie,生产环境必须开启,本地HTTP调试可临时设为false
        SameSite = SameSiteMode.Lax, // 限制跨站携带,防CSRF攻击,无跨站需求可设为Strict
        Expires = DateTimeOffset.UtcNow.AddHours(2) // 和JWT本身的过期时间保持一致
    };
    // 写入Cookie
    Response.Cookies.Append("AccessToken", jwtToken, cookieOpt);

    return Ok(new { msg = "登录成功" });
}

3. 登出逻辑实现

登出时直接删除对应Cookie即可,常规业务场景不需要额外做JWT失效处理,如果需要支持令牌立即作废,可以配合分布式缓存维护一个令牌黑名单。

[HttpPost("logout")]
public IActionResult Logout()
{
    Response.Cookies.Delete("AccessToken");
    return Ok();
}

关键注意点:

  • 生产环境绝对不要关闭Cookie的Secure属性,否则令牌会通过HTTP明文传输,存在泄露风险
  • HttpOnly = true是Cookie存储比localStorage存储安全的核心配置,必须开启
  • 如果项目存在跨域接口调用场景,跨域配置需要开启AllowCredentials,同时前端请求要配置withCredentials: true,否则Cookie不会自动携带
  • 访问令牌过期时间建议设置在2小时以内,需要长会话可以额外实现刷新令牌机制,刷新令牌同样存储在HttpOnly安全Cookie中

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 16:30:43