【问题标题】:Where and how to store the access token and refresh token访问令牌和刷新令牌的存储位置和方式
【发布时间】:2025-11-28 18:10:02
【问题描述】:

我有一个 dotnet core 2.2 MVC web 应用程序,它使用 web api 来执行一些数据库查询。我已经为 web api 实现了基于 JWT 令牌的身份验证。令牌在 api 处生成,Web 应用程序已收到访问令牌、到期令牌和刷新令牌。我需要将此令牌详细信息存储在我的客户端,以便我可以使用它来访问 Web api(到期前)或在令牌过期时使用刷新令牌生成新令牌。

对此的任何帮助将不胜感激。

【问题讨论】:

  • 令牌应该存储在 cookie 中,但请确保您从服务器设置它
  • 你能解释一下吗?
  • 看看下面我的回答

标签: asp.net-core-mvc jwt token


【解决方案1】:

以前的答案没有对使用这些解决方案的原因提供明确的解释。

典型系统如下图所示,WEB 中使用了两种常见的客户端应用程序架构:

  • 在浏览器中运行的单页应用程序
  • 服务器端 MVC 应用程序

在 SPA 的情况下,令牌存储在浏览器(会话存储或本地存储)中,并在过期时由浏览器或应用程序本身自动清除。 仅供参考,出于安全原因,在 SPA 中无法获取刷新令牌。

如果是 MVC 应用程序(您的情况),事情会变得更加复杂。您有两个选择:将其存储在仅 http cookie 或某些外部会话存储中。 Aspnet 核心支持这两种情况,但每种情况都有一些警告。 A good article here。简而言之,如果您担心 cookie 大小,请使用 分布式会话存储,这会增加系统架构的复杂性。否则 cookie 是最简单的解决方案,并且在 aspnet core 中默认启用,您只需要设置 options.StoreTokens = trueoptions.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme

【讨论】:

    【解决方案2】:

    有多种方法可以存储令牌。通常应用程序不会在任何地方存储访问令牌,但它们会将刷新令牌存储在永久存储中。

    我们来看看web端和api端需要存储什么。

    首先,用户将请求使用凭据登录 Web 应用程序,Web 应用程序会将这个请求传递给与 DB 交互的 api 项目。

    现在,api 将生成访问令牌和刷新令牌,并将刷新令牌保存到该数据库。然后,Web api 需要将访问令牌和刷新令牌存储在 cookie 或会话等临时存储中。

    访问令牌过期时;您需要调用一个新令牌,这将更新数据库中之前的刷新令牌。

    TL;DR

    刷新令牌 - 在数据库中

    访问令牌和刷新令牌-web临时存储

    【讨论】:

    • 是的,你是对的。现在我需要实现第二部分,即“访问令牌和刷新令牌 - Web 临时存储”。然后只有我可以发送访问令牌和刷新令牌以获取新令牌。
    • 我有一个问题,如果我将访问令牌存储在数据库中,可能存在哪些安全漏洞?
    • 好问题!正如您所认为的将访问令牌存储在数据库中;您需要在每次请求进入时调用您的数据库,只是为了验证用户,这会增加系统的额外负载。 @NoorAshuvo
    【解决方案3】:

    您有多种选择(安全的 http-only cookie、本地存储、会话存储等)。

    在最简单的情况下,您可以将其存储在 cookie 中,以便与每个请求一起发送:

    • cookie 应始终具有HttpOnly 标志,以防止浏览器中的 XSS 攻击。
    • cookie 还应在生产中使用Secure 标志,以确保 cookie 仅通过 HTTPS 发送。
    • 保护您的表单免受 CSRF 攻击(例如,通过使用 ASP.NET Core 的 AntiForgery 功能)。

    【讨论】:

      【解决方案4】:

      从 ui 调用 Web 应用程序服务器(控制器)控制器,该控制器又调用以从 api 获取令牌。 从 api 响应中获取令牌并将其存储在 cookie 中。

      你的控制器应该看起来像这样

      var option = new CookieOptions
      {
          Expires = DateTime.Now.AddMinutes(response.ExpiresIn)
      };
      
      if (!string.IsNullOrEmpty(domain))
      {
                      option.Domain = domain;
      }
      
      Response.Cookies.Append({cookiename}, response.AccessToken, option);
      

      【讨论】:

        最近更新 更多