在 JWT 中设置角色是最佳实践吗?

我正在考虑使用 JWT。在 举个例子中,我在有效载荷数据中看到以下信息:

"admin": true

管理员可以被认为是一个角色,因此我的问题。在令牌有效载荷中设置角色是一种惯例/良好做法吗?考虑到角色可以动态修改,我很疑惑。

76289 次浏览

没有什么可以阻止您创建声明来在令牌中存储额外的信息,如果它们对您的客户端有用的话。

然而,我只依靠 JWT 来处理 认证(调用者是谁)。如果需要执行 授权(调用方可以执行的操作) ,请从持久存储中查找调用方角色/权限,以获得最新的值。

对于短期的令牌(例如,在微服务集群中传播身份验证和授权时) ,我发现在令牌中包含角色非常有用。

如前所述,ASP.NET Core 将自动检测 JWT 中提到的任何 roles:

{
"iss": "http://www.jerriepelser.com",
"aud": "blog-readers",
"sub": "123456",
"exp": 1499863217,
"roles": ["Admin", "SuperUser"]
}

并将它们映射到 ASP.NET 角色ASP.NET 角色通常用于保护应用程序的某些部分。

[Authorize(Roles = "Admin")]
public class SettingsController : Controller

发布(和签名) JWT 的服务器通常被称为 < em > 授权 服务器,而不仅仅是 认证服务器,因此在 JWT 中包含角色信息(或范围)是有意义的,即使它们不是 已登记的申索

作为 JWT 的用例,官方 JWT 站点显式地 提到“授权”(与“身份验证”相反) :

什么时候应该使用 JSON Web 令牌? 授权: 这是使用 JWT 的最常见场景。一旦用户登录,每个后续请求都将包含 JWT,允许用户访问该令牌所允许的路由、服务和资源。单点登录是目前广泛使用 JWT 的一个特性,因为它的开销很小,而且能够很容易地跨不同域使用。

也就是说,从安全角度来看,您应该三思而后行,无论您是否真的希望在令牌中包含角色或权限。

(下面的文字可以理解为一个更“深入”的后续行动,相当简短的接受的答案)

一旦创建并签名了令牌,您将授予权限,直到令牌过期。但是如果不小心授予了管理员权限会怎样呢?在令牌过期之前,有人正在您的站点上使用错误分配的权限进行操作。

有些人可能会争辩说这种象征是短暂的,但是考虑到一个人在短时间内可能造成的伤害,这不是一个有力的论据。其他一些人主张为令牌维护一个单独的黑名单数据库表,这解决了令牌无效的问题,但是增加了某种类型的会话状态跟踪到后端,因为你现在需要跟踪所有当前的会话-所以你必须在每次请求到达时对黑名单进行 db 调用,以确保它还没有被列入黑名单。有人可能会说,这首先违背了“将角色放入 JWT 以避免额外的 db 调用”的目的,因为您刚刚用额外的“角色 db-call”换取了额外的“黑名单 db-call”。

因此,您可以将有关用户角色和权限的信息保存在您的 auth-server 的 db 中,而不是将授权声明添加到令牌中,您可以在任何时候对这些信息拥有完全的控制权(例如,撤销某个用户的某个权限)。如果请求到达,则从 auth-server (或存储权限的任何地方)获取当前角色。

顺便说一下,如果查看 IANA 登记的公众索赔列表,您将看到这些声明是围绕身份验证发展的,而不是处理用户被允许做的事情(授权)。

总而言之,你可以..。

  • 如果(a)方便对你来说很重要,(b)你想避免额外的数据库调用来获取权限,(c)不关心小时窗口,在这个窗口中一个人拥有他不应该拥有的权限,(d)你不关心(轻微)增加 JWT 的有效载荷大小由于增加权限。

  • 将角色添加到 JWT 中,并使用黑名单 ,如果(a)你想阻止任何时间窗口,在这个时间窗口中,一个人拥有他不应该拥有的权限; (b)接受对每个传入请求向黑名单发出请求的代价; (c)你不关心(轻微)增加权限导致 JWT 有效负载大小的增加。

  • 不要在 JWT 中添加角色,而是根据需要获取角色 如果(a)你想阻止某个人拥有他不应该拥有的权限的任何时间窗口,或者(b)避免黑名单的开销,或者(c)避免增加 JWT 有效负载的大小以略微增加,或者(d)如果你接受这样做的代价是有时/总是在传入请求中查询角色。