C#和ASP.NET Core 6:在“会话”中进行身份验证和用户详细信息

3

这篇文章可能会让我收到很多"好的爷爷"评论。

我已经读了十几篇文章和在这个主题上找到的每一个 SO 的问题。

我可能离开得太久或完全错过了什么,因为我发誓用户验证曾经非常简单。我记得以前内置方法和服务器上的会话只是通过 cookie 或类似的方式简单地知道用户是谁,并且能够存储信息“在会话中”。我甚至不记得过去几年设置身份验证,它只是内置在新应用程序中的。

相反,我能找到的最简洁的指南非常复杂。我认为我需要一个令牌授权/身份验证设置,因为现在可能有像应用程序之类的消费者没有典型的 cookie 模式。在我的头脑中,令牌就像一个 cookie,只不过它手动保存在用户端并通过每个请求的标头传递?

值得赞扬的是,该指南成功了,至少对于登录和正确使用控制器中的简单Authorize属性。然而,User.Identity.Name总是为空,即使User.Identity.IsAuthenticatedtrue,这令人困惑。

我认为身份验证是如何工作的:

  • 用户请求使用用户名/密码的 API
  • 服务检查组合,并将加密的 JWT 返回给用户
  • 用户在每个请求中发送 JWT
  • 服务器解密此 JWT 以识别用户-这可能是我错了的地方

所以我的问题来了:

我需要更多关于用户的数据,比如访问整个UserModel等未来请求的会话信息,其中一个用户通过在授权标头中使用 JWT 身份验证而不是 cookie 进行标识,但我不想每次都去数据库找它。这就是我认为应该只有一个内存中的会话对象,但是在令牌身份验证中似乎并非如此。


TL;DR:

在以 JWT 身份验证为代替 cookie 的情况下,在哪里放置特定于用户的短期(“会话”)信息,以供将来的请求消费?

  • Session state不正确,因为它与 cookie 硬连线
  • HttpContext.Items不正确,因为它只适用于一个请求
  • Cache存储不正确,因为它不是用户/会话特定的。我可能会在这里创建一个类似会话的用户键控存储,但这似乎过于过度工程化。
  • 基本上,任何我将所有数据(而不仅仅是用户标识符)传递给客户端,然后依赖客户端将其传递回来的做法都是错误的?但随时纠正我。

JWT身份验证令牌与状态是分开的。它实际上是一个安全的用户标识符令牌。如果服务器仍然发送会话状态cookie,则应用正常的cookie会话状态。而且,即使没有直接使用cookie,只要有一个安全的用户标识符,就可以实现面向用户的状态(这实际上就是将用户绑定信息保存到数据库中的方法);无论如何,可以创建自定义的“Session”状态提供程序。 - user2864740
你的项目身份验证设置为Windows还是匿名?请确保没有使用匿名。 - JobesK
JWT是基于声明的;我可能错了,但在你的链接中似乎他们在创建令牌时添加了声明。如果您可以填充声明,它们将存在并且可以在受保护的端点中访问。 - ChiefTwoPencils
1个回答

3

服务器解密该JWT以识别用户,这可能是我出错的地方。

JWT令牌并未加密,而是签名,因此您无法更改它。例如,在jwt.io上可以打开它。

如果我要以JWT在Authorization标头中识别用户而不是Cookie,我将在哪里放置特定于用户、短期(“会话”)信息以供将来的请求使用?

您可以将其放置在令牌的主要声明中。在您提供的指南中写到:

  var claims = new List<Claim>
  {
       new Claim(JwtRegisteredClaimNames.NameId, user.UserName)
  };

你可以添加任何你想要存储到令牌中的声明,稍后你可以通过以下方式访问这些数据:

var claim = _contextAccessor.HttpContext.User?.Claims.FirstOrDefault(d =>
                    d.Type == ClaimTypes.NameIdentifier);

你也不能使用你列出来的其它例子,例如 HttpContext.Items,因为它们没有签名。如果令牌被任何方式修改,系统将识别并返回401错误。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接