Play 框架和 JSON Web 令牌

Posted

技术标签:

【中文标题】Play 框架和 JSON Web 令牌【英文标题】:Play Framework & JSON Web Token 【发布时间】:2014-04-24 04:26:51 【问题描述】:

是否有 JWT 的 Scala 实现或至少有 Play 的示例?在发布了this question 之后,我在 Internet 上进行了进一步搜索,发现了一些 JWT 的介绍。任何建议将不胜感激。

【问题讨论】:

【参考方案1】:

我在spray.io 应用程序中使用Nimbus-JOSE-JWT,对此我非常满意。执行身份验证的对象扩展了 HttpAuthenticator,如果找到正确的 JWT,则返回令牌主题和相关信息,否则返回 None(身份验证失败)。使用 Play2,您可以使用 like this 实现 HTTP 基本身份验证。关于我认为您更感兴趣的令牌设置/获取:

首先,创建一个私钥/公钥对(我使用了this code 的一部分)。创建从文件系统初始化时加载密钥的身份验证对象。

使用这些密钥创建一个 com.nimbusds.jose.crypto.MACSigner 和一个 com.nimbusds.jose.crypto.MACVerifier。

每当您想设置密钥时,首先对其进行加密,然后对其进行签名。加密:

private def encrypt(subject: String) = 
   val header = new JWEHeader(JWEAlgorithm.RSA_OAEP, EncryptionMethod.A128GCM)
   val jwt = new EncryptedJWT(header, claimSet(subject))
   val encrypter = new RSAEncrypter(publicKey.asInstanceOf[java.security.interfaces.RSAPublicKey])
   jwt.encrypt(encrypter)
   jwt.serialize()

claimSet 方法可预测地返回一组声明:

def claimSet(subject: String) = 
   val jwtClaims = new JWTClaimsSet()
   jwtClaims.setIssuer(Config.JWT.issuer)
   jwtClaims.setSubject(subject)
   jwtClaims.setJWTID(java.util.UUID.randomUUID().toString())
   jwtClaims

publicKey 属性是从KeyFactory.getInstance("RSA").generatePublic 返回的值。

签名:

private def sign(jwt: String) = 
   val jwsObject = new JWSObject(new JWSHeader(JWSAlgorithm.HS256), new Payload(jwt))
   jwsObject.sign(Tokens.signer)
   jwsObject.serialize

鉴于上述情况,当您收到密钥时,您需要先验证签名,然后再解密。为了验证,首先您尝试使用com.nimbusds.jose.JWSObject.parse(my_token) 解析它,只要它不抛出ParseException,您就可以在parse 返回的JWSObject 上调用verify,使用您所返回的MACVerifier 作为参数较早创建。如果verify返回true,你只需要在同一个JWSObject上调用getPayload.toString就可以得到验证的payload。

要解密经过验证的有效载荷,您可以在其上调用com.nimbusds.jwt.EncryptedJWT.parse,然后类似:

val decrypter = new RSADecrypter(privateKey.asInstanceOf[java.security.interfaces.RSAPrivateKey])
jwt.decrypt(decrypter)

privateKey 是从KeyFactory.getInstance("RSA").generatePrivate 返回的值。

然后您可以使用jwt.getJWTClaimsSet 获取声明集。

最后,关于设置 Authorization 标头,我正在使用this post 中提到的原则在我的 AngularJS 客户端上执行此操作。

【讨论】:

是的,您所描述的或多或少是我所做的。我也使用 nimbusds……但我不加密 JWT……我只是用应用程序的秘密对其进行签名,以确保它没有被篡改。由于我使用 HTTPS,令牌加密只是无用的开销。无论如何,非常感谢您的出色解释:-)

以上是关于Play 框架和 JSON Web 令牌的主要内容,如果未能解决你的问题,请参考以下文章

在 Play 中请求 Content-Type! REST Web 服务框架

如何解析JSON使用Play框架

Java/Play 中的 JSON 代理!框架

使用 Play 以 JSON 形式返回验证错误!框架

JSON Web 令牌过期和记住我功能

Play框架JSON读取:如何读取String或Int?