2015-12-08 43 views
0

我要保護我的應用程序與此所需的對象:play.api.mvc.Result錯誤

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一部分,我發現了以下錯誤:

type mismatch; found : Object required: play.api.mvc.Result

什麼是錯的?

+1

看看每個代碼塊返回的類型。 Scala推斷Object,因爲它們不同。 –

回答

2

這裏的問題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"""")) 
    } 
    } 

注意,拆包在<-左手側被轉換爲filtermatch