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

.NET6 MVC客户端获取Web API JWT令牌后实现用户登录咨询

实现方案

你的架构是MVC客户端作为前端交互层、Web API作为后端服务层,这种场景下不需要直接把裸JWT暴露给浏览器存储,标准做法是客户端拿到JWT后先做合法性校验,校验通过后调用Cookie认证的SignInAsync方法完成本地登录,把JWT存在加密的认证Cookie对应的身份声明中,后续调用API时再从身份信息里取出JWT携带在请求头中。


第一步:登录成功后写入本地认证Cookie

你现在已经能拿到API返回的token,不要直接把JWT明文存到普通Cookie或localStorage中,按以下流程处理:

  1. 强烈建议先在客户端本地校验JWT的签名、过期时间、签发方/受众,校验规则和Web API端的TokenValidationParameters保持一致,过滤伪造、过期的无效token。
  2. 构造用户身份声明集合,把JWT作为单独的声明存入,再调用HttpContext.SignInAsync写入加密的HttpOnly认证Cookie,完成本地登录。

对应登录接口的POST动作实现代码参考:

// 注意:你的登录接口必须接收用户名密码参数,且必须用POST方法,不要用GET传敏感信息
[HttpPost]
public async Task<IActionResult> Login(LoginModel model, [FromServices] IConfiguration config)
{
    using (var client = new HttpClient())
    {
        client.BaseAddress = new Uri("https://localhost:7157/");
        // 把用户名密码放到请求体传给API校验
        var reqContent = new FormUrlEncodedContent(new Dictionary<string, string>
        {
            ["username"] = model.Username,
            ["password"] = model.Password
        });
        HttpResponseMessage response = await client.PostAsync("WeatherForecast/login", reqContent);
        if (response.IsSuccessStatusCode)
        {
            var tokenResult = await response.Content.ReadFromJsonAsync<TokenModel>();
            string jwtToken = tokenResult.Token;

            // 本地校验JWT合法性,参数和API端保持一致
            var tokenHandler = new JwtSecurityTokenHandler();
            var validationParams = new TokenValidationParameters
            {
                ValidateIssuer = true,
                ValidateAudience = true,
                ValidAudience = config["Jwt:Audience"],
                ValidIssuer = config["Jwt:Issuer"],
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(config["Jwt:Key"])),
                ValidateLifetime = true,
                ClockSkew = TimeSpan.Zero
            };
            try
            {
                // 校验不通过会直接抛出异常
                var claimsPrincipal = tokenHandler.ValidateToken(jwtToken, validationParams, out _);
                // 追加专门存JWT的声明,后续调用API时直接取用
                var userIdentity = (ClaimsIdentity)claimsPrincipal.Identity;
                userIdentity.AddClaim(new Claim("AccessToken", jwtToken));

                // 写入本地认证Cookie,完成登录
                await HttpContext.SignInAsync(
                    CookieAuthenticationDefaults.AuthenticationScheme,
                    new ClaimsPrincipal(userIdentity),
                    new AuthenticationProperties
                    {
                        IsPersistent = model.RememberMe,
                        ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(20) // 和Cookie配置的过期时间对齐
                    });

                return RedirectToAction("Index", "Home");
            }
            catch
            {
                ModelState.AddModelError("", "登录凭证无效,请重试");
                return View(model);
            }
        }
        ModelState.AddModelError("", "用户名或密码错误");
        return View(model);
    }
}

第二步:后续调用Web API时自动携带JWT

JWT不需要暴露给前端浏览器,MVC端后续需要调用API时,直接从当前登录用户的声明里取出之前存储的AccessToken,放到请求的Authorization头中即可:

public async Task<IActionResult> GetWeatherList([FromServices] IConfiguration config)
{
    // 从当前用户身份中取JWT
    string accessToken = User.FindFirstValue("AccessToken");
    using (var client = new HttpClient())
    {
        client.BaseAddress = new Uri("https://localhost:7157/");
        // 携带JWT调用API
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
        var data = await client.GetFromJsonAsync<IEnumerable<WeatherForecast>>("WeatherForecast");
        return View(data);
    }
}

必须注意的实践要点

  • 你当前Web API端的登录接口标记为[HttpGet]属于严重安全隐患,GET请求的参数会留在浏览器历史、服务日志中,必须改成POST方法,校验完用户名密码后再颁发JWT。
  • 不要把JWT存在localStorage或者非HttpOnly的Cookie中,容易被XSS攻击窃取。通过SignInAsync生成的认证Cookie默认是加密、HttpOnly的,安全性高很多。
  • MVC客户端不需要同时启用JWT认证,只保留Cookie认证作为本地登录态凭证即可,JWT仅作为MVC服务和Web API之间的通信凭证,不需要暴露给前端浏览器。
  • 如果JWT过期,可以在MVC端做全局请求拦截,要么跳回登录页,要么配合refresh token自动刷新后,更新用户声明里的AccessToken并重新调用SignInAsync写入Cookie即可。
  • 如果你完全信任内网部署的Web API返回结果,也可以跳过本地JWT校验步骤,直接解析JWT里的用户ID、角色等信息构造身份声明完成登录,但公网部署场景必须加本地校验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 18:39:35