【问题标题】:parse.json of authenticated play request已验证播放请求的 parse.json
【发布时间】:2012-04-07 12:46:54
【问题描述】:

我在我的应用程序中设置了这样的身份验证,当提供用户名且 API 密钥为 123 时始终允许:

object Auth  {
    def IsAuthenticated(block: => String => Request[AnyContent] => Result) = {
      Security.Authenticated(RetrieveUser, HandleUnauthorized) { user =>
        Action { request =>
          block(user)(request)
        }
      }
    }

    def RetrieveUser(request: RequestHeader) = {

      val auth = new String(base64Decode(request.headers.get("AUTHORIZATION").get.replaceFirst("Basic", "")))
      val split  = auth.split(":")
      val user = split(0)
      val pass = split(1)
      Option(user)
    }

    def HandleUnauthorized(request: RequestHeader) = {
      Results.Forbidden
    }

    def APIKey(apiKey: String)(f: => String => Request[AnyContent] => Result) = IsAuthenticated { user => request =>

      if(apiKey == "123")
        f(user)(request)
      else
        Results.Forbidden
    }

}

然后我想在我的控制器(在本例中为 testOut)中定义一个方法,该方法仅将请求用作 application/json。现在,在我添加身份验证之前,我会说“def testOut = Action(parse.json) {...}”,但是现在我正在使用身份验证,如何将 parse.json 添加到混合中并制作这份工作?

  def testOut = Auth.APIKey("123") { username => implicit request =>

    var props:Map[String, JsValue] = Map[String, JsValue]()
    request.body  match {
      case JsObject(fields) => { props = fields.toMap }
      case _ => {} // Ok("received something else: " + request.body + '\n')
    }

    if(!props.contains("UUID"))
      props.+("UUID" -> UniqueIdGenerator.uuid)

    if (!props.contains("entity"))
      props.+("entity" -> "unset")

    props.+("username" -> username)

    Ok(props.toString)
  }

作为一个额外的问题,为什么只有 UUID 添加到道具映射中,而不是实体和用户名?

抱歉,我正在尝试同时学习 Scala 和 Play。 :-)

干杯

尼克

【问题讨论】:

  • PS,如果这里还有其他我明显做错的事情,请随时指出,这样我可以朝着正确的方向前进:-)
  • 您可以使用map(key) = value 代替map.+(key -> value)map.getOrElseUpdate(key, value) 代替if (!map.contains(key) map(key) = value)
  • 您可以使用case _ => 代替case _ => {}。而且这里不需要花括号:case JsObject(fields) => { props = fields.toMap }
  • 您正在使用不可变映射(因为toMap 返回不可变映射),因此您无法更新它。并且Map 的方法+ 创建了一个新地图,而不更新当前地图。您可以使用map += key -> value 将地图替换为新版本。
  • 非常感谢@senia 的地图输入。 :-) 关于在哪里添加 parse.json 以获得 Request[JsValue] 而不是 Request[AnyContent] 的任何建议?

标签: json scala authentication playframework playframework-2.0


【解决方案1】:

原来我根本不需要使用bodyparser,request.body有一个asJson函数可以使用。所以我利用它来做以下事情。这项工作,我可以继续我的工作,但我仍然不太明白如何在这里获取 JSON 正文解析器。学习中……;-)

def testOut = Auth.APIKey("123") { username => request =>

  var props:Map[String, JsValue] = Map[String, JsValue]()
  request.body.asJson  match {
    case None => {}
    case Some(x) => {
      x match {
        case JsObject(fields) => { props = fields.toMap }
        case _ => {} // Ok("received something else: " + request.body + '\n')
      }
    }
  }

  if(!props.contains("UUID"))
    props += "UUID" -> toJson(UniqueIdGenerator.uuid)

  if(!props.contains("entity"))
    props += "entity" -> toJson("unset")

  props += "should" -> toJson("appear")
  props += "username" -> toJson(username)

  Ok(props.toString)
}

【讨论】:

  • 再一次,也请留下 cmets 关于任何应该做不同的事情:-)
  • Option 用法的一些改进:var props = request.body.asJson.collect{ case JsObject(fields) => fields.toMap}.getOrElse(Map())
  • 我不会将可变对象用作this tutorial 引号:在代码中使用 val 会让您考虑替代的、不可变的、函数式代码。这个小例子演示了删除 var 会导致重构。重构导致新的编码模式。新的编码模式会导致您的编程方法发生转变。这种方法的转变导致了具有更少缺陷且更易于维护的变革性代码。。这需要一点时间来适应,但这是要走的路!
【解决方案2】:

在这里查看我对这个问题的回答:Play 2.0 Framework, using a BodyParser with an authenticated request

要点是我重载了 IsAuthenticated 方法以将BodyParser 作为参数并用它调用Action

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-18
    • 1970-01-01
    相关资源
    最近更新 更多