我目前正在使用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的新手,非常感谢有关解决上述问题的任何指示或提示!谢谢!