使用REST Http进行Akka身份验证

时间:2019-05-08 08:55:25

标签: scala rest akka

我正在使用Akka Basic身份验证和scala测试Json HTTP路由。但是路线无法按需运行。这是代码

首先,安全路由不适用于邮递员BasicAuth。我需要添加电子邮件“ secured/test@test.com”以触发登录操作。其次,子路由篮筐角色根本不起作用。邮差说未知路线。那么,如何使用Postman BasicAuth Http标头来实现此目的?我必须只发送“安全的”或与电子邮件和密码一起发送的请求。 第二,我该如何使子路线basketActor / add工作。

~ Route.seal {
          (pathPrefix("secured") & get) {
            authenticateBasic(realm = "secure site", myUserPassAuthenticator) { email =>
              path(Segment) { segment =>
                var user = User.USER_LIST.find(_.id == segment)
                if (user.isDefined)
                  complete(s"Hi '$email' you logged in")
                else complete(s"login failed Please register at ${"users" / "register"}")
              }
            } ~ path("basketActor") {
              (pathEnd & get) {
                implicit val timeout = Timeout(3 seconds)
                onSuccess((basketActor ? GetBasketProducts).mapTo[BasketList]) { res =>
                  complete(BasketContainer(products = res.products))
                }
              } ~ (path("add" / IntNumber) & post) { number =>
                val product = Product.PRODUCT_LIST.find(_.id == number)
                if (product.isDefined) {
                  product.foreach { product =>
                    basketActor ! AddProductToBasket(product)
                    //            complete(Basket.BASKET_LIST ::= product)
                  }
                  complete(product)
                } else complete("Not found")
              }
            }
          }
      }
 def myUserPassAuthenticator(credentials: Credentials): Option[String] =
      credentials match {
        case p@Credentials.Provided(id) if p.verify("secret") => Some(id)
        case _ => None
      }

因此,我的预期结果是用户调用安全的Route登录,然后他可以访问basketActor路由。但是现在该路由不可访问,安全路由也无法正常工作

1 个答案:

答案 0 :(得分:1)

这是Akka HTTP中基本身份验证的工作方式:

HTTP请求中的Authorization标头用于基本身份验证,它包含使用base64编码编码的用户名和密码。 authenticateBasic路由将从标头中提取此信息以创建Credentials对象,然后将其传递给您的myUserPassAuthenticator方法。此方法应检查用户名和密码是否匹配,如果成功,则应返回代表您系统中该用户的对象,或在失败时返回None

authenticateBasic的第二个(咖喱)参数是一个获取用户数据并返回Route的函数。因此,在您的情况下,email参数将包含id返回的myUserPassAuthenticator值。此函数应返回包含所有需要身份验证的路径的路由。


重要的是要意识到,没有使用基本身份验证“登录”的概念。只有正确或不正确的身份验证凭据。 (如果要具有登录/注销语义,则需要转到基于令牌的身份验证机制。)


因此,要使路由正常工作,您需要将查找用户ID的逻辑移到myUserPassAuthenticator中,并返回user对象作为结果。碰巧的是,您仅可以返回find的结果,因为它已经返回了Option[User]

您还需要确保所有经过身份验证的路由都在authenticateBasic路由内。当前basketActoradd路由处于同一级别,因此未通过身份验证。


示例路线如下所示。我认为更清楚地使用了concat而不是~

pathPrefix("secured") {
  authenticateBasic(realm = "secure site", myUserPassAuthenticator) { user =>
    concat(
      (pathEnd | pathSingleSlash) {
        get {
          complete(s"User $user Authenticated OK")
        }
      },
      path("basketActor") {
        (pathEnd & get) {
          complete(s"basketActor for $user")
        }
      },
      path("add" / IntNumber) { number =>
        post {
          complete(s"User $user posted $number")
        }
      }
    )
  }
}

请注意,用户ID(电子邮件地址)不在URL中,而是在Basic Authentication标头中的请求中。

要用Postman进行测试,您需要创建一个URL为GET.../secured的{​​{1}},或者一个URL为.../secured/basketActor的{​​{1}}。在POST标签下,您需要选择.../secured/add/1并在其中添加凭据。

相关问题