Akka аутентификация с REST Http - PullRequest
0 голосов
/ 08 мая 2019

Я тестирую Json HTTP Routes с базовой аутентификацией Akka и scala.Но маршруты не работают по мере необходимости.Вот код

Во-первых, защищенный маршрут не работает с почтальоном BasicAuth.Мне нужно добавить адрес электронной почты "secured/test@test.com", чтобы активировать вход в систему.Во-вторых, подчиненный корзинатор не работает вообще.Почтальон говорит неизвестный маршрут.Итак, как я могу сделать это с помощью Postman BasicAuth Http Header?Какой запрос мне нужно отправить только «защищенным» или с электронной почтой и паролем вместе. Во-вторых, как я могу заставить работать subroutes 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
      }

Поэтому мой ожидаемый результат должен бытьпользователь вызывает защищенный маршрут, входит в систему и получает доступ к маршруту basketActor, но теперь этот маршрут недоступен и защищенный маршрут также не работает

1 Ответ

1 голос
/ 08 мая 2019

Так работает базовая аутентификация в Akka HTTP:

Заголовок Authorization в HTTP-запросе используется для базовой аутентификации и содержит имя пользователя и пароль, закодированные с использованием кодировки base64. Маршрут authenticateBasic извлечет эту информацию из заголовка для создания объекта Credentials, а затем передаст ее в метод myUserPassAuthenticator. Этот метод должен проверить, что имя пользователя и пароль совпадают, и в случае успеха он должен вернуть объект, представляющий этого пользователя в вашей системе, или вернуть None при ошибке.

Второй (карри) аргумент authenticateBasic - это функция, которая принимает пользовательские данные и возвращает Route. Таким образом, в вашем случае аргумент email будет содержать значение id, возвращаемое myUserPassAuthenticator. Эта функция должна возвращать маршрут, который содержит все пути, требующие аутентификации.


Важно понимать, что не существует концепции "входа в систему" с базовой аутентификацией. Есть только учетные данные, которые являются правильными или неправильными. (Если вы хотите иметь семантику входа / выхода, вам нужно перейти к механизму аутентификации на основе токенов).


Итак, чтобы заставить ваши маршруты работать, вам нужно переместить логику, которая ищет идентификатор пользователя в myUserPassAuthenticator и вернуть в результате объект user. Как это бывает, вы можете просто вернуть результат find, потому что это уже возвращает Option[User].

Вам также необходимо убедиться, что все аутентифицированные маршруты находятся внутри маршрута authenticateBasic. В настоящее время маршруты basketActor и add находятся на одном уровне и, следовательно, не проходят проверку подлинности.


Примерный маршрут будет выглядеть следующим образом. Я использовал 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")
        }
      }
    )
  }
}

Обратите внимание, что идентификатор пользователя (адрес электронной почты) отсутствует в URL-адресе, он указан в запросе в заголовке Basic Authentication.

Чтобы проверить это с почтальоном, вам нужно создать GET с URL .../secured или .../secured/basketActor, или POST с URL .../secured/add/1. На вкладке Auth необходимо выбрать Basic Authentication и добавить туда учетные данные.

...