【问题标题】:Object required: play.api.mvc.Result error所需对象:play.api.mvc.Result 错误
【发布时间】:2015-12-10 20:52:39
【问题描述】:

我想用这个来保护我的应用程序

def Secured[A](username: String, password: String)(action: Action[A]) = Action(action.parser) { 
 request =>   request.headers.get("Authorization").flatMap { authorization =>
    authorization.split(" ").drop(1).headOption.filter { 
       encoded => new String(org.apache.commons.codec.binary.Base64.decodeBase64(encoded.getBytes)).split(":").toList match {
        case u :: p :: Nil if u == username && password == p => true
        case _ => false
      }
    }.map(_ => action(request))   }.getOrElse {
    Unauthorized.withHeaders("WWW-Authenticate" -> """Basic realm="Secured"""")   } }

但在getOrElse 部分,我收到以下错误:

类型不匹配;找到:所需对象:play.api.mvc.Result

怎么了?

【问题讨论】:

  • 查看每个代码块返回的类型。 Scala 推断 Object 因为它们是不同的。

标签: scala playframework-2.0


【解决方案1】:

问题在于action(request) 正在返回Future[Result] 而不仅仅是Result。所以getOrElse之前的整个表达式的类型是Option[Future[Result]],它等待Future[Result]作为getOrElse的参数。

所以首先你可以将你的 Unauthorized.withHeaders 东西包装成 Future.successfull( ... )

接下来是整个表达式的结果是Future[Result],它不是Action.apply(bodyParser)( ... ) 的正确参数类型,但有Action.async 方法可以处理它。

所以具有最小类型更正\重构的整个更正块是

import org.apache.commons.codec.binary.Base64

def secured[A](username: String, password: String)(action: Action[A]) =
  Action.async(action.parser) {
    request => request.headers.get("Authorization").flatMap { authorization =>
      authorization.split(" ").drop(1).headOption.filter { encoded =>
        val bytes = Base64.decodeBase64(encoded.getBytes)
        new String(bytes).split(":").toList match {
          case u :: p :: Nil if u == username && password == p => true
          case _ => false
        }
      }.map(_ => action(request))
    }.getOrElse {
      Future.successful(
        Unauthorized.withHeaders(
          "WWW-Authenticate" -> """Basic realm="Secured""""))
    }
  }

进一步的糖注射可能会导致更具可读性的版本:

import org.apache.commons.codec.binary.Base64

def secured[A](username: String, password: String)(action: Action[A]) =
  Action.async(action.parser) { request =>
    val result = for {
      authorization <- request.headers.get("Authorization")
      Array(_, encoded, _*) <- Some(authorization.split(" "))
      bytes = Base64.decodeBase64(encoded.getBytes)
      credentials = new String(bytes).split(":").toList
      List(`username`, `password`) <- Some(credentials)
    } yield action(request)

    result.getOrElse {
      Future.successful(
        Unauthorized.withHeaders(
          "WWW-Authenticate" -> """Basic realm="Secured""""))
    }
  }

请注意,&lt;- 左侧的解包转换为 filtermatch

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-07
    • 1970-01-01
    • 1970-01-01
    • 2016-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多