我目前正在使用 Play Silhouette 4.0 作为我的身份验证库,使用 Play 2.5 (Scala) 构建 REST Api。
我需要使每个用户的 JWT 无效,因此我需要将身份验证器保留在数据库(mongodb)中。我正在使用 ReactiveMongo 0.12.1。
按照 Silhouette 的 CacheAuthenticatorRepository 和 ReactiveMongo 的 MongoAuthInfoDAO 的代码示例,我为 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 的新手,希望能提供有关解决上述问题的任何指示或提示!谢谢!!