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

ASP.NET前端用户无法通过[Authorize]验证:手动存JWT到Cookie无效

前端用户身份验证失败问题求助

调用「Login」API从后端获取JWT Token后,手动将其存储到Cookie中,但访问带有[Authorize]特性的Razor页面控制器Action时,始终提示用户未认证。

想知道是否必须调用httpContext.SignInAsync()?见过一些应用未调用该方法仍能完成用户认证,请问我遗漏了什么?

相关配置代码

services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddCookie(options =>
               {
                   options.LoginPath = "/auth";
                   options.AccessDeniedPath = "/auth/accessdenied";
                   options.Cookie.IsEssential = true;
                   options.SlidingExpiration = true; 
                   double expiresIn = 3600;
                   options.ExpireTimeSpan = TimeSpan.FromSeconds(expiresIn);
                   options.Cookie.Name = SConstants.JWT_COOKIE_NAME;
                   options.Cookie.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Strict;
               });

// middleware

app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(
        name: "default",
        pattern: "{controller=Home}/{action=Index}/{id?}");
});

存储Token的代码

HttpContext.Response
           .Cookies
           .Append(SConstants.JWT_COOKIE_NAME, 
                   access_token, 
                   new CookieOptions 
                       {
                           HttpOnly = true, 
                           Secure = true 
                       });

问题分析与解决方案
  • 核心矛盾:认证方案与存储方式不匹配
    你当前配置的是Cookie认证方案,但手动存储原始JWT到Cookie的逻辑和该方案不兼容。Cookie认证依赖的是ASP.NET Core生成的加密身份Cookie(内含用户声明等信息),而非你直接存入的原始JWT,所以中间件无法识别这个Cookie的身份信息。

  • 是否必须调用SignInAsync()?
    针对你当前的Cookie认证配置,必须调用。这个方法会按照Cookie认证的规则生成加密的身份Cookie,让ASP.NET Core的认证中间件能正确解析用户身份。

  • 为什么有些应用不用SignInAsync()也能认证?
    这类应用大多配置的是JWT Bearer认证方案:要么把JWT放在Authorization: Bearer <token>请求头中,要么通过自定义逻辑从Cookie读取JWT,同时后端配置了AddJwtBearer()来直接验证Token,这种场景不需要调用SignInAsync()。

  • 两种可行修正方案
    方案1:遵循Cookie认证的标准流程
    在Login API获取用户信息后,调用SignInAsync()生成合规的认证Cookie,替代手动存储JWT的操作:

    // 构造用户身份声明
    var claims = new List<Claim>
    {
        new Claim(ClaimTypes.Name, "用户名"),
        new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
    };
    var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
    var authProperties = new AuthenticationProperties
    {
        ExpiresUtc = DateTimeOffset.UtcNow.AddHours(1),
        IsPersistent = false,
        AllowRefresh = true
    };
    
    await HttpContext.SignInAsync(
        CookieAuthenticationDefaults.AuthenticationScheme,
        new ClaimsPrincipal(claimsIdentity),
        authProperties);
    

    执行后ASP.NET Core会自动生成符合要求的认证Cookie,后续请求时中间件能正确识别用户身份。

    方案2:切换为JWT Bearer认证(适合依赖JWT的场景)

    1. 修改服务配置,添加JWT Bearer认证并配置从Cookie读取Token:
    services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        {
            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuer = true,
                ValidateAudience = true,
                ValidateLifetime = true,
                ValidateIssuerSigningKey = true,
                ValidIssuer = "你的Issuer",
                ValidAudience = "你的Audience",
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("你的密钥"))
            };
            // 自定义从Cookie读取JWT的逻辑
            options.TokenRetriever = request => request.Cookies[SConstants.JWT_COOKIE_NAME];
        });
    
    1. 保留你手动存储JWT到Cookie的代码,此时认证中间件会直接从Cookie读取并验证JWT,无需调用SignInAsync()。
  • 当前代码的遗漏点
    你配置了Cookie认证,但没有生成该方案要求的加密身份Cookie,而是存入了原始JWT,导致Cookie认证中间件无法解析用户身份,最终判定为未认证。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 03:01:04