2014-02-18 24 views
0

我想實現類似於此示例的認證機制:播放2.2 EssentialAction隨着期貨

def HasToken(action: String => EssentialAction): EssentialAction = EssentialAction { requestHeader => 
     val maybeToken = requestHeader.headers.get("X-SECRET-TOKEN") 
     maybeToken map { token => 
     action(token)(requestHeader) // apply requestHeader to EssentialAction produces the Iteratee[Array[Byte], SimpleResult] 
     } getOrElse { 
     Done(Unauthorized("401 No Security Token\n")) // 'Done' means the Iteratee has completed its computations 
     } 
    } 

然而,在我的情況,我映射一個隨機令牌值存儲在服務器端的會話在Mongodb。目標是能夠讓用戶隨意終止所有其他會話。

不過,我從ReactiveMongo獲得的數據將被包裹在一個未來。

我想是這樣的:

def HasToken(action: String => EssentialAction): EssentialAction = EssentialAction { requestHeader => 
     val maybeToken = requestHeader.headers.get("session") 
     maybeToken map { token => 
     //This returns a future.. 
     Session.find(session).map { result => 
      result match 
      case Some(session) => action(session)(requestHeader) 
      case None => Done(Unauthorized()) 
     } 
     } getOrElse { 
     Done(Unauthorized("401 No Security Token\n")) // 'Done' means the Iteratee has completed its computations 
     } 
    } 

這可能與EssentialAction?

回答

2

Iteratee.flatten從變所以你可以做這樣的:

def HasToken(action: String => EssentialAction): EssentialAction = EssentialAction { requestHeader => 
    val maybeToken = requestHeader.headers.get("session") 

    val futureIteratee: Future[Iteratee[Array[Byte], SimpleResult]] = maybeToken map { token => 
    //This returns a future.. 
    Session.find(token).map { 
     case Some(session) => action(session)(requestHeader) 
     case None => Done[Array[Byte], SimpleResult](Unauthorized("Invalid token")) 
    } 
    } getOrElse { 
    Future.successful(Done[Array[Byte], SimpleResult](Unauthorized("401 No Security Token\n"))) 
    } 

    Iteratee.flatten(futureIteratee) 
} 
+0

我得到一個'found:scala.concurrent.Future [play.api.libs.streams.Accumulator [akka.util.ByteString,play.api.mvc.Result]]','required:scala.concurrent.Future [play .api.libs.iteratee.Iteratee [?,?]]'......可能我錯過了一些東西(沒有這個很正確)! –

1

您可以使用ActionBuilder作爲invokeBlock方法返回一個Future [SimpleResult]這樣你就可以flatMap你將來變成一個調用底層塊

喜歡的東西

object Authenticated extends ActionBuilder[AuthenticatedRequest] { 
    def invokeBlock[A](request: Request[A], block: (AuthenticatedRequest[A]) => Future[SimpleResult]) = { 
    Session.find(session).map { result => 
     result match 
     case Some(session) => block(new AuthenticatedRequest(session)) 
     case None => Unauthorized() 
    }   
} 

}

其中AuthenticatedRequest是您的請求類型的包裝你的會話對象

+0

注意,有行動和EssentialAction之間的一個重要區別,即動作總是解析請求主體,而EssentialAction讓你收到請求頭忽略了後襬脫困境身體。例如,這可能對防止DoS攻擊非常重要。 – johanandren