gpt4 book ai didi

scala - 如何实现多个Silhouette Authenticator?

转载 作者:行者123 更新时间:2023-12-02 04:38:04 41 4
gpt4 key购买 nike

我使用了play-silhouette-seed作为我的应用程序的模板。因此,在我的项目中,我使用基于 cookie 的身份验证器 (CookieAuthenticator)。即使对于通过嵌入在我的 Twirl 模板中的 JavaScript 进行的 REST 调用,这也绝对可以正常工作。但是,现在我还想在浏览器以外的客户端中以编程方式进行 REST 调用。因此,我必须检索每个响应上的 Set-Cookie:authenticator=... 元素,并将其设置为我的请求的一部分。在嵌入我的 Twirl 模板并在浏览器中呈现的 JavaScript 代码片段中,这不是问题,因为我不必处理这个问题,但对于其他客户端(服务器等)来说,这会导致头痛。

除了我的 CookieAuthenticator 之外,我现在还想实现一个 JWTAuthenticator。这是否受支持,或者我是否必须完全切换到 JWTAuthenticator ?此外,即使除了身份验证器之外的所有内容都应该是相同的实现,我是否需要单独的操作?

最佳答案

是的,Silhouette 允许您实现多个 authenticators 。以下是如何实现 JWTAuthenticator 提供 JWT 身份验证器服务以及您的 CookieAuthenticator :

  1. 正如 Douglas Liu 在评论中已经指出的那样,您需要创建一个额外的 environment 类型。它应该将Identity与相应的Authenticator连接起来。

例如:

trait CookieEnv extends Env {
type I = Account
type A = CookieAuthenticator
}

trait JWTEnv extends Env {
type I = Account
type A = JWTAuthenticator
}
  • 在 Silhouette 模块中实现 JWT 绑定(bind)。请查看play-silhouette-angular-seed 获取完整示例。
  • 例如:

    class SilhouetteModule extends AbstractModule with ScalaModule {

    def configure() {
    bind[Silhouette[CookieEnv]].to[SilhouetteProvider[CookieEnv]]
    bind[Silhouette[JWTEnv]].to[SilhouetteProvider[JWTEnv]]
    // ...
    ()
    }

    @Provides
    def provideCookieEnvironment(
    userService: AccountService,
    authenticatorService: AuthenticatorService[CookieAuthenticator],
    eventBus: EventBus): Environment[CookieEnv] = {

    Environment[CookieEnv](
    userService,
    authenticatorService,
    Seq(),
    eventBus
    )
    }

    @Provides
    def provideJWTEnvironment(
    userService: AccountService,
    authenticatorService: AuthenticatorService[JWTAuthenticator],
    eventBus: EventBus): Environment[JWTEnv] = {

    Environment[JWTEnv](
    userService,
    authenticatorService,
    Seq(),
    eventBus
    )
    }

    // ...

    @Provides
    def provideCookieAuthenticatorService(
    @Named("authenticator-cookie-signer") cookieSigner: CookieSigner,
    @Named("authenticator-crypter") crypter: Crypter,
    fingerprintGenerator: FingerprintGenerator,
    idGenerator: IDGenerator,
    configuration: Configuration,
    clock: Clock): AuthenticatorService[CookieAuthenticator] = {

    val config = configuration.underlying.as[CookieAuthenticatorSettings]("silhouette.authenticator")
    val encoder = new CrypterAuthenticatorEncoder(crypter)

    new CookieAuthenticatorService(config, None, cookieSigner, encoder, fingerprintGenerator, idGenerator, clock)
    }

    @Provides
    def provideJWTAuthenticatorService(
    @Named("authenticator-crypter") crypter: Crypter,
    idGenerator: IDGenerator,
    configuration: Configuration,
    clock: Clock): AuthenticatorService[JWTAuthenticator] = {

    val config = configuration.underlying.as[JWTAuthenticatorSettings]("silhouette.authenticator")
    val encoder = new CrypterAuthenticatorEncoder(crypter)

    new JWTAuthenticatorService(config, None, encoder, idGenerator, clock)
    }

    // ...

    }
  • 添加JWTAuthenticator configuration settings到您的silhouette.conf:
  • 例如:

    authenticator.fieldName = "X-Auth-Token"
    authenticator.requestParts = ["headers"]
    authenticator.issuerClaim = "Your fancy app"
    authenticator.authenticatorExpiry = 12 hours
    authenticator.sharedSecret = "!!!changeme!!!"
  • 创建单独的路由以通过 JWT 进行身份验证:
  • 例如,在您的 app.routes 文件中,添加以下行:

    # JWT Authentication
    POST /api/jwt/authenticate controllers.auth.api.AuthController.authenticate
  • 最后,在您的 AuthController 中,添加相应的authenticate 方法。
  • 示例代码(改编自 SignInController.scala ):

    implicit val dataReads = (
    (__ \ 'email).read[String] and
    (__ \ 'password).read[String] and
    (__ \ 'rememberMe).read[Boolean]
    ) (SignInForm.SignInData.apply _)

    def authenticate = Action.async(parse.json) { implicit request =>
    request.body.validate[SignInForm.SignInData].map { signInData =>
    credentialsProvider.authenticate(Credentials(signInData.email, signInData.password)).flatMap { loginInfo =>
    accountService.retrieve(loginInfo).flatMap {
    case Some(user) => silhouette.env.authenticatorService.create(loginInfo).map {
    case authenticator if signInData.rememberMe =>
    val c = configuration.underlying
    authenticator.copy(
    expirationDateTime = clock.now + c.as[FiniteDuration]("silhouette.authenticator.rememberMe.authenticatorExpiry"),
    idleTimeout = c.getAs[FiniteDuration]("silhouette.authenticator.rememberMe.authenticatorIdleTimeout")
    )
    case authenticator => authenticator
    }.flatMap { authenticator =>
    Logger.info(s"User ${user._id} successfully authenticated.")
    silhouette.env.eventBus.publish(LoginEvent(user, request))
    silhouette.env.authenticatorService.init(authenticator).map { token =>
    Ok(Json.obj("token" -> token))
    }
    }
    case None => Future.failed(new IdentityNotFoundException("Couldn't find user."))
    }
    }.recover {
    /* Login did not succeed, because user provided invalid credentials. */
    case e: ProviderException =>
    Logger.info(s"Host ${request.remoteAddress} tried to login with invalid credentials (email: ${signInData.email}).")
    Unauthorized(Json.obj("error" -> Messages("error.invalidCredentials")))
    }
    }.recoverTotal {
    case e: JsError =>
    Logger.info(s"Host ${request.remoteAddress} sent invalid auth payload. Error: $e.")
    Future.successful(Unauthorized(Json.obj("error" -> Messages("error.invalidPayload"))))
    }
    }

    关于scala - 如何实现多个Silhouette Authenticator?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42209678/

    41 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com