1

私は 1 つのプロジェクトを開発しており、Silhouette認証フレームワークを使用しています。ブラウザ UI からの通常のリクエストには CookieAuthenticator を使用し、REST API リクエストには JWTAuthenticator を使用します。これは、このことが実際にどのように機能するかを完全に理解していないと感じさせるドキュメント付きの Silhouette ソースコードの一部です。

/**
 * 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、アプリをシャットダウンしても、生成されたトークンは有効のままになります。しかし、バッキング ストアがなければ、これらのトークンはどのように有効に保たれるのでしょうか? アプリを再度起動して同じトークンを使用すると、ユーザーが認証されます。そして、それがどのようにこれを行うのかわかりません。説明していただけますか?

4

1 に答える 1

2

とても簡単です。既知のソルトとアルゴリズムの組み合わせでトークンの内容をエンコードします。JWT トークンには、HMAC または RSA でエンコードされた既知の構造があります。サーバーは、たとえばエンコーディング キー (HMAC の秘密キー) と RSA のキーペアを知っている限り、ステートレスな方法でトークンを復号化できます。

巧妙になり、内部をチェックしたい場合は、独自のものを作成することもできます。JWT は標準化されており、アカウントは通常iss、慣例によりフィールドの下で使用できます。たとえば、Google Cloud では、issは Google サービス アカウントのメールアドレスであるため、あなたが誰であるかを知ることができます。

さらに調べると、独自のsessionオブジェクトを作成し、それをトークンにエンコードできます。

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使用されたシークレットの値を知っている限り、トークンをステートレスに検証し、ユーザー情報を抽出できます。エンコードを実行します。

于 2016-04-11T10:27:31.187 に答える