Deadbolt2 -> SecureSocial/ Силуэт Интеграция
Как кому-нибудь удалось интегрировать Deadbolt2 с Silhouette/SecureSocial?
Я нахожу, что Silhouette Authorization немного базова, и Deadbolt2 отвечает всем требованиям.
Спасибо
1 ответ
Я набросал грубый подход здесь, но я буду развивать его до полного рабочего примера на основе шаблона активатора play-silhouette-seed-master, когда у меня будет время.
Требуются два основных шага.
Во-первых, ваш com.mohiva.play.silhouette.api.Identity
реализация также должна реализовать be.objectify.deadbolt.scala.models.Subject
,
Во-вторых, позаимствовать код из com.mohiva.play.silhouette.api.RequestHandlerBuilder
и интегрировать его в свой DeadboltHandler
реализация.
import javax.inject.Inject
import be.objectify.deadbolt.scala.models.Subject
import be.objectify.deadbolt.scala.{ AuthenticatedRequest, DeadboltHandler, DynamicResourceHandler }
import com.mohiva.play.silhouette.api.{ LoginInfo, RequestProvider, Silhouette }
import com.mohiva.play.silhouette.impl.authenticators.CookieAuthenticator
import models.User
import play.api.mvc.Results._
import play.api.mvc.{ Request, Result }
import utils.auth.DefaultEnv
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
class MyDeadboltHandler @Inject() (silhouette: Silhouette[DefaultEnv]) extends DeadboltHandler {
override def beforeAuthCheck[A](request: Request[A]): Future[Option[Result]] = Future.successful(None)
override def getSubject[A](request: AuthenticatedRequest[A]): Future[Option[Subject]] =
if (request.subject.isDefined) {
Future.successful(request.subject)
} else {
// this else branch is taken from com.mohiva.play.silhouette.api.RequestHandlerBuilder
silhouette.env.authenticatorService.retrieve(request).flatMap {
// A valid authenticator was found so we retrieve also the identity
case Some(a) if a.isValid =>
silhouette.env.identityService.retrieve(a.loginInfo).map(i => i)
// An invalid authenticator was found so we needn't retrieve the identity
case Some(a) if !a.isValid => Future.successful(None)
// No authenticator was found so we try to authenticate with a request provider
case None => handleRequestProviderAuthentication(request).flatMap {
// Authentication was successful, so we retrieve the identity and create a new authenticator for it
case Some(loginInfo) => silhouette.env.identityService.retrieve(loginInfo).flatMap { (i: Option[User]) =>
silhouette.env.authenticatorService.create(loginInfo)(request).map((a: CookieAuthenticator) => i)
}
// No identity and no authenticator was found
case None => Future.successful(None)
}
}
}
// this whole function is taken from com.mohiva.play.silhouette.api.RequestHandlerBuilder
private def handleRequestProviderAuthentication[B](implicit request: Request[B]): Future[Option[LoginInfo]] = {
def auth(providers: Seq[RequestProvider]): Future[Option[LoginInfo]] = {
providers match {
case Nil => Future.successful(None)
case h :: t => h.authenticate(request).flatMap {
case Some(i) => Future.successful(Some(i))
case None => if (t.isEmpty) Future.successful(None) else auth(t)
}
}
}
auth(silhouette.env.requestProviders)
}
override def onAuthFailure[A](request: AuthenticatedRequest[A]): Future[Result] =
Future.successful(request.subject.map(subject => Redirect(controllers.routes.ApplicationController.index()))
.getOrElse(Redirect(controllers.routes.SignInController.view())))
override def getDynamicResourceHandler[A](request: Request[A]): Future[Option[DynamicResourceHandler]] = Future.successful(None)
}
В ваших контроллерах теперь вы можете использовать ограничения Deadbolt вместо полномочий Silhouette. Например...
class ApplicationController @Inject() (
val messagesApi: MessagesApi,
silhouette: Silhouette[DefaultEnv])
extends Controller with I18nSupport {
def index = silhouette.SecuredAction.async { implicit request =>
Future.successful(Ok(views.html.home(request.identity)))
}
}
можно заменить на
class ApplicationController @Inject() (
val messagesApi: MessagesApi,
deadbolt: ActionBuilders)
extends Controller with I18nSupport {
def index = deadbolt.SubjectPresentAction().defaultHandler() { implicit request =>
Future.successful(Ok(views.html.home(request.subject)))
}
}