ReactiveMongo与Play Silhouette JWT Authenticator

时间:2017-07-04 08:18:19

标签: scala playframework-2.5 reactivemongo silhouette

我目前正在使用Play 2.5(Scala)使用Play Silhouette 4.0作为我的身份验证库来构建REST Api。

我需要使每个用户的JWT无效,因此我需要在数据库(mongodb)中保留身份验证器。我正在使用ReactiveMongo 0.12.1。

按照Silhouette的CacheAuthenticatorRepository和MongoAuthInfoDAO for ReactiveMongo的代码示例,我已经为JWT Authenticator创建了一个身份验证器存储库,如下所示:

    package modules

    import javax.inject.Inject

    import com.mohiva.play.silhouette.api.StorableAuthenticator
    import com.mohiva.play.silhouette.api.repositories.AuthenticatorRepository
    import modules._
    import com.mohiva.play.silhouette.api.util._

    import scala.concurrent.Future
    import scala.concurrent.duration.Duration
    import scala.reflect.ClassTag

    import com.mohiva.play.silhouette.api.{ AuthInfo, LoginInfo }
    import com.mohiva.play.silhouette.persistence.exceptions.MongoException
    import play.api.Configuration
    import play.api.libs.concurrent.Execution.Implicits._
    import play.api.libs.json.{ Format, JsObject, Json }
    import play.modules.reactivemongo.ReactiveMongoApi
    import play.modules.reactivemongo.json._
    import reactivemongo.api.commands.WriteResult
    import reactivemongo.play.json.collection.JSONCollection

    import play.api.libs.json.Reads

    /**
     * Implementation of the authenticator repository which uses the reactive mongo to persist the authenticator.
     *
     * @param cacheLayer The cache layer implementation.
     * @tparam T The type of the authenticator to store.
     */
    class MongoAuthenticatorRepository[JWTAuthenticator] @Inject() (reactiveMongoApi: ReactiveMongoApi)
      extends AuthenticatorRepository[JWTAuthenticator] {

      def collection: Future[JSONCollection] = reactiveMongoApi.database.map(_.collection("jwt.auth.repo"))

      /**
       * Finds the authenticator for the given ID.
       *
       * @param id The authenticator ID.
       * @return The found authenticator or None if no authenticator could be found for the given ID.
       */
      override def find(id: String): Future[Option[JWTAuthenticator]] = {
        //cacheLayer.find[JWTAuthenticator](id)
        val query = Json.obj("id" -> id)
        collection.flatMap(_.find(query).one[JWTAuthenticator])
      }

      /**
       * Adds a new authenticator.
       *
       * @param authenticator JWTAuthenticatorhe authenticator to add.
       * @return JWTAuthenticatorhe added authenticator.
       */
      override def add(authenticator: JWTAuthenticator): Future[JWTAuthenticator] = {
        //cacheLayer.save[JWTAuthenticator](authenticator.id, authenticator, Duration.Inf)
        val obj = Json.obj("id" -> authenticator.id , "authenticator" -> authenticator, "duration" -> Duration.Inf)
        collection.flatMap(_.insert(obj))
      }

      /**
       * Updates an already existing authenticator.
       *
       * @param authenticator JWTAuthenticatorhe authenticator to update.
       * @return JWTAuthenticatorhe updated authenticator.
       */
      override def update(authenticator: JWTAuthenticator): Future[JWTAuthenticator] = {
        //cacheLayer.save[JWTAuthenticator](authenticator.id, authenticator, Duration.Inf)
        val obj = Json.obj("id" -> authenticator.id , "authenticator" -> authenticator, "duration" -> Duration.Inf)
        collection.flatMap(_.update(Json.obj("id" -> authenticator.id), obj, upsert = true))
      }

      /**
       * Removes the authenticator for the given ID.
       *
       * @param id JWTAuthenticatorhe authenticator ID.
       * @return An empty future.
       */
      override def remove(id: String): Future[Unit] = {
        //cacheLayer.remove(id)
        val query = Json.obj("id" -> id)
        collection.flatMap(_.remove(query))
      }
    }

然后我通过修改我的silhouette.module文件来实现它:

      @Provides def provideAuthenticatorService(authenticatorEncoder: AuthenticatorEncoder, idGenerator: IDGenerator, configuration: Configuration, clock: Clock): AuthenticatorService[JWTAuthenticator] = {
          val config = new JWTAuthenticatorSettings(
            fieldName = configuration.underlying.getString("silhouette.authenticator.fieldName"),
            //requestParts = Some(configuration.underlying.getAs[Seq[RequestPart.Value]]("silhouette.authenticator.requestParts").get),
            issuerClaim = configuration.underlying.getString("silhouette.authenticator.issuerClaim"),
            sharedSecret = configuration.underlying.getString("silhouette.authenticator.sharedSecret"),
            authenticatorExpiry = configuration.underlying.getAs[FiniteDuration]("silhouette.authenticator.authenticatorExpiry").get,
            authenticatorIdleTimeout = Some(configuration.underlying.getAs[FiniteDuration]("silhouette.authenticator.authenticatorIdleTimeout").get)
          )
          implicit lazy val format = Json.format[JWTAuthenticator]
          val repo = new MongoAuthenticatorRepository[JWTAuthenticator]
          new JWTAuthenticatorService(config, repo, authenticatorEncoder, idGenerator, clock)
        }

我在编译代码时遇到问题,显示的错误是:

"No Json deserializer found for type JWTAuthenticator. Try to implement an implicit Reads or Format for this type."

"Imported `MongoAuthenticatorRepository' is permanently hidden by definition of class MongoAuthenticatorRepository in package modules"

我也尝试实现自定义JWTAuthenticator类,并在随播对象中设置隐式格式。然而,错误仍然存​​在。

我是Scala以及Play Framework的新手,非常感谢有关解决上述问题的任何指示或提示!谢谢!

0 个答案:

没有答案