【问题标题】:Play 2.2 EssentialAction With Futures玩 2.2 EssentialAction 与期货
【发布时间】:2014-03-19 00:48:16
【问题描述】:

我正在尝试实现类似于此示例的身份验证机制:

    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 获得的数据将被包装在 Future 中。

我想要这样的东西:

    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 可以做到这一点吗?

【问题讨论】:

    标签: scala playframework playframework-2.2 reactivemongo


    【解决方案1】:

    Iteratee.flatten 来自 Future[Iteratee[A, E]] => Iteratee[A, E],所以你可以这样做:

    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)
    }
    

    【讨论】:

    • 我收到了 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[?,?]]... 可能我遗漏了一些东西(不太正确)!
    【解决方案2】:

    您可以使用 ActionBuilder 作为 invokeBlock 方法返回 Future[SimpleResult] 以便您可以将您的未来平面映射到对底层块的调用

    有点像

    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 是包装会话对象的请求类型

    【讨论】:

    • 请注意,Action 和 EssentialAction 之间有一个重要区别,即 Action 将始终解析请求正文,而 EssentialAction 允许您在收到忽略正文的请求标头后退出。例如,这对于防止 DoS 攻击可能很重要。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-11-04
    • 1970-01-01
    • 2012-09-19
    • 1970-01-01
    • 2015-12-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多