2014-02-18 25 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