Вопрос или проблема
Я пытаюсь добавить аутентификацию JWT в своё API приложения на Akka HTTP Scala.
Я использую зависимости Maven jwt-circe
и jwt-core
из репозитория Maven.
Однако текущий код вызывает ошибки типов
:
case Some(jwtToken) if Jwt.isValid(jwtToken, secretKey, Seq(JwtAlgorithm.HS256))
Ошибка типа: ни один из перегруженных альтернатив метода isValid в трейте JwtCore с типами
.
onComplete(Jwt.decode(jwtToken, secretKey, Seq(JwtAlgorithm.HS256)))
Ошибка типа: ни один из перегруженных альтернатив метода decode в трейте JwtCore с типами
.
Снова, я установил обе зависимости jwt-circe
и jwt-core
(проверьте код sbt
).
Не могли бы вы помочь мне определить проблему?
Заранее спасибо!
Мой текущий код выглядит следующим образом:
Классы:
final case class Account(name: String, age: Int, country: String, roles: List[String])
object JsonFormats {
import DefaultJsonProtocol._
implicit val accountFormat: RootJsonFormat[Account] = jsonFormat4(Account.apply)
Код JWT:
import pdi.jwt.{ Jwt, JwtAlgorithm, JwtClaim, JwtCirce }
private val expiresIn = 1 * 24 * 60 * 60
implicit val clock: Clock = Clock.systemUTC
private val secretKey = "vp-akka-http-jwt"
def authenticated: Directive1[Account] =
optionalHeaderValueByName("Authorization").flatMap {
case Some(jwtToken) if Jwt.isValid(jwtToken, secretKey, Seq(JwtAlgorithm.HS256)) =>
getClaims(jwtToken) match {
case Some(account) => provide(account)
case None => reject(AuthorizationFailedRejection).toDirective[Tuple1[Account]]
}
case t => println(t.get)
complete(StatusCodes.Unauthorized)
}
private def getClaims(jwtToken: String): Option[Account] = {
onComplete(Jwt.decode(jwtToken, secretKey, Seq(JwtAlgorithm.HS256))){
case Success(value) =>
Some(value.content.parseJson.convertTo[Account])
case Failure(ex) => None
}
}
Конфигурация SBT:
lazy val akkaHttpVersion = "10.6.3"
lazy val akkaVersion = "2.9.4"
resolvers += "Akka library repository".at("https://repo.akka.io/maven")
fork := true
lazy val root = (project in file(".")).
settings(
inThisBuild(List(
organization := "com.example",
scalaVersion := "3.3.3"
)),
name := "eskimi-bidding-agent",
libraryDependencies ++= Seq(
// ....
("com.github.jwt-scala" %% "jwt-circe" % "10.0.1")
.exclude("io.circe", "circe-parser_3")
.exclude("io.circe", "circe-core_3")
.exclude("org.typelevel", "cats-kernel_3")
.exclude("org.typelevel", "cats-core_3")
.exclude("io.circe", "circe-numbers_3")
.exclude("org.typelevel", "jawn-parser_3")
.exclude("io.circe", "circe-jawn_3"),
"com.github.jwt-scala" %% "jwt-core" % "10.0.1",
// ....
)
)
Ответ или решение
Чтобы решить вашу проблему с ошибками типа, связанными с методами isValid
и decode
в библиотеке JWT для Scala, давайте сначала проверим, правильно ли вы используете эти методы и соответствующие зависимости.
Ошибка и ее причины
Ваши ошибки связаны с тем, что вы пытаетесь использовать методы isValid
и decode
, которые требуют различных типов аргументов. Основные причины могут быть в следующем:
- Неправильные параметры: Убедитесь, что вы передаете правильные параметры в методы.
- Несоответствие типов: Вероятно, проблема в том, что передаваемые вами значения не соответствуют ожидаемым типам методов.
Шаги для исправления
- Проверьте зависимости:
Убедитесь, что вы используете совместимые версии библиотек. В вашем примере вы используетеjwt-circe
иjwt-core
версии10.0.1
, которые должны быть совместимы между собой.
"com.github.jwt-scala" %% "jwt-core" % "10.0.1"
"com.github.jwt-scala" %% "jwt-circe" % "10.0.1"
-
Измените код аутентификации:
- Убедитесь, что вы передаете правильные аргументы в методы
isValid
иdecode
. Вот исправленный код:
- Убедитесь, что вы передаете правильные аргументы в методы
import pdi.jwt.{Jwt, JwtAlgorithm, JwtClaim, JwtCirce}
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Directive1
import scala.util.{Success, Failure}
private val secretKey = "vp-akka-http-jwt"
def authenticated: Directive1[Account] =
optionalHeaderValueByName("Authorization").flatMap {
case Some(jwtToken) if Jwt.isValid(jwtToken, secretKey, Seq(JwtAlgorithm.HS256)) =>
getClaims(jwtToken) match {
case Some(account) => provide(account)
case None => reject(AuthorizationFailedRejection)
}
case _ => complete(StatusCodes.Unauthorized)
}
private def getClaims(jwtToken: String): Option[Account] = {
Jwt.decode(jwtToken, secretKey, Seq(JwtAlgorithm.HS256)) match {
case Success(claim) => Some(claim.content.parseJson.convertTo[Account])
case Failure(_) => None
}
}
- Проверьте парсинг JSON:
Убедитесь, что ваш классAccount
и его формат JSON корректно определены. Возможно, вам нужно добавить имплицитное преобразование дляAccount
вJsonFormats
, если вы это еще не сделали (как показано в вашем исходном коде).
Итоговый код:
Вот окончательный вариант вашего кода с учетом вышеуказанных правок:
import pdi.jwt.{Jwt, JwtAlgorithm, JwtClaim, JwtCirce}
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.model.StatusCodes
import scala.util.{Success, Failure}
import spray.json._
final case class Account(name: String, age: Int, country: String, roles: List[String])
object JsonFormats {
import DefaultJsonProtocol._
implicit val accountFormat: RootJsonFormat[Account] = jsonFormat4(Account)
}
private val secretKey = "vp-akka-http-jwt"
def authenticated: Directive1[Account] =
optionalHeaderValueByName("Authorization").flatMap {
case Some(jwtToken) if Jwt.isValid(jwtToken, secretKey, Seq(JwtAlgorithm.HS256)) =>
getClaims(jwtToken) match {
case Some(account) => provide(account)
case None => reject(AuthorizationFailedRejection)
}
case _ => complete(StatusCodes.Unauthorized)
}
private def getClaims(jwtToken: String): Option[Account] = {
Jwt.decode(jwtToken, secretKey, Seq(JwtAlgorithm.HS256)) match {
case Success(claim) => Some(claim.content.parseJson.convertTo[Account])
case Failure(_) => None
}
}
Заключение
После выполнения указанных действий ваша проблема с аутентификацией JWT в Akka HTTP должна быть решена. Убедитесь, что вы также протестировали свою логику аутентификации, чтобы гарантировать правильное поведение вашего API. Если появятся новые ошибки, проверьте стек-трейсы, чтобы лучше понять, из-за чего они возникают, и устранить причины.