将 JWT 与 Ktor 一起使用并在声明中包含用户信息

Posted

技术标签:

【中文标题】将 JWT 与 Ktor 一起使用并在声明中包含用户信息【英文标题】:Using JWT with Ktor and including user info in claim 【发布时间】:2018-08-14 21:36:35 【问题描述】:

我已经成功地在我的应用程序中包含了一个 jwt 身份验证令牌,并且能够限制对端点的访问。我想将用户的 ID 嵌入到 jwt 令牌中,但我正在努力如何在 Ktor 中实现 jwt 验证器。

我为客户端创建一个令牌,如下所示:

val token = JWT.create().withAudience(audience).withIssuer(issuer).withClaim("userId", "XXX").sign(algorithm)

路线是这样设置的。 authentication 块在服务器启动时运行,并且不允许使用 userId 创建验证程序。

这来自 jwt 样本:

route("/api") 
    authentication 
        val jwtVerifier = makeJwtVerifier(issuer, audience)
        jwtAuthentication(jwtVerifier, realm)  credential ->
        if (credential.payload.audience.contains(audience))
            JWTPrincipal(credential.payload)
        else
            null
    

    handle 
       // Handle jwt succcess here
    


private fun makeJwtVerifier(issuer: String, audience: String): JWTVerifier = JWT
        .require(algorithm)
        .withAudience(audience)
        .withIssuer(issuer)
        .build()

这样做的正确方法是什么?我知道我需要为每个请求创建一个验证器,但不知道在哪里执行此操作,也不知道这是否可取。

【问题讨论】:

【参考方案1】:

你应该在这里实现它。您不需要检查用户 ID 的验证器。

jwtAuthentication(jwtVerifier, realm)  credential ->
  if (credential.payload.audience.contains(audience))
    val userId = credential.payload.claims["userId"].asString()
    // check if user exists ... if you want

    JWTPrincipal(credential.payload)
  else
    null

【讨论】:

我明白你的建议,但如果令牌是用 userId 签名的,验证器将如何工作?这将需要 userId 进行验证。 @GaryBak 令牌未使用用户 ID 签名,令牌使用发行实体(您的服务)的私钥签名。您输入的用户 ID 只是令牌中的“声明”之一。当您在上面编写的验证程序代码运行签名和任何到期日期时,ktor 已经验证了。 感谢@Strelok,经过一番调试后,我意识到我所拥有的是正确的,并且我在我的 post 方法中搞砸了对 userId 的检查。您对上面的 userId 的检查确实有效。感谢您的帮助。

以上是关于将 JWT 与 Ktor 一起使用并在声明中包含用户信息的主要内容,如果未能解决你的问题,请参考以下文章

Ktor websockets 身份验证

在验证之前使用 JWT 有效负载

什么是JWT

如何在 JWT 中包含身份角色声明?

Ktor application.conf - Jwt 配置

在进行 ajax 调用时在 HTTP 标头中包含 JWT