Scala 剪影JWT令牌如何在无状态模式下保持有效?

Scala 剪影JWT令牌如何在无状态模式下保持有效?,scala,playframework,silhouette,Scala,Playframework,Silhouette,我正在开发一个项目并使用身份验证框架。 对于来自浏览器UI的常规请求,我使用CookieAuthenticator,对于RESTAPI请求,我使用JWTAuthenticator。 下面是一部分带有文档的剪影源代码,它让我觉得我不完全理解这个东西是如何工作的: /** * The service that handles the JWT authenticator. * * If the authenticator DAO is deactivated then a stateless a

我正在开发一个项目并使用身份验证框架。 对于来自浏览器UI的常规请求,我使用CookieAuthenticator,对于RESTAPI请求,我使用JWTAuthenticator。 下面是一部分带有文档的剪影源代码,它让我觉得我不完全理解这个东西是如何工作的:

/**
 * The service that handles the JWT authenticator.
 *
 * If the authenticator DAO is deactivated then a stateless approach will be used. But note
 * that you will loose the possibility to invalidate a JWT.
 *
 * @param settings The authenticator settings.
 * @param dao The DAO to store the authenticator. Set it to None to use a stateless approach.
 * @param idGenerator The ID generator used to create the authenticator ID.
 * @param clock The clock implementation.
 * @param executionContext The execution context to handle the asynchronous operations.
 */
class JWTAuthenticatorService(
  settings: JWTAuthenticatorSettings,
  dao: Option[AuthenticatorDAO[JWTAuthenticator]],
  idGenerator: IDGenerator,
  clock: Clock)(implicit val executionContext: ExecutionContext)
  extends AuthenticatorService[JWTAuthenticator]
  with Logger {
注意文档的这一部分

如果已停用验证器DAO,则将使用无状态方法 被使用。但请注意,您将失去无效的可能性 JWT


因此,它的工作原理正是他们所说的。当我将
None
作为
dao
参数的值传递时,生成的令牌保持有效,即使我关闭了应用程序。但如果没有支持存储,这些代币如何保持有效?当我再次启动应用程序并使用相同的令牌时,它会对用户进行身份验证。我不知道它是怎么做到的。你能解释一下吗?很简单。使用已知的salt和算法组合对令牌的内容进行编码。JWT令牌具有已知的结构,使用HMAC或RSA编码。服务器可以以无状态方式解密令牌,只要它们知道编码密钥(HMAC的密钥)和RSA的密钥对(例如)

如果你想变得聪明,你甚至可以自己做,看看里面的东西。JWT是标准化的,根据惯例,账户通常在
iss
字段下可用。例如,在谷歌云中,
iss
是你的谷歌服务帐户电子邮件,因此他们可以知道你是谁

进一步探索,您可以创建自己的
会话
对象并将其编码为令牌

case class Session(user: UUID, timestamp: String, email: String)

// This is roughly the process used.
object TokenEncoder {
  val secret = Play.current.configuration.getString("encryption.key")
  def encode(session: Session): String = { 
    // The below line is just to make a point.
    AES.encrypt(Json.toJson(session), someSharedKey)
  }

  def decode(str: String): Option[Session] = {
    Json.parse(AES.decrypt(str, someSharedKey)).asOpt[Session]
  }
}

在跨服务器请求的情况下,该令牌的字符串值可以在cookie或标头中使用,并且每台服务器都可以无状态地验证令牌并提取用户信息,只要他们知道用于执行编码的密钥
someSharedKey
。使用已知的salt和算法组合对令牌的内容进行编码。JWT令牌具有已知的结构,使用HMAC或RSA编码。服务器可以以无状态的方式解密令牌,只要它们知道编码密钥(HMAC的秘钥)和RSA的密钥对。是的,如果我想得更仔细一点,我会猜显然令牌本身应该嵌入有关链接帐户的信息。不过,服务器可以轻松解密令牌这一事实对我来说并不简单。你能把你的评论作为回答吗?这样我就可以接受了?