繁体   English   中英

Scala、ZIO、Tapir - 如何从 header 检索授权令牌?

[英]Scala, ZIO, Tapir - how to retrieve authorization token from header?

我创建了貘端点:

val getEndpoint = endpoint.get
  .securityIn(auth.bearer[String]())
  .in("players" / path[PlayerId]("playerId"))
  .in(query[PlayerRequest]("query"))
  .errorOut(someErrors)    

现在,我想读取所有传递的值: bearer tokenplayerIdquery 所以我创建了ZIO服务器逻辑:

PlayersEndpoint.getEndpoint.zServerLogic { case (playerId, query) => 
  //some logic to do...
}

它工作正常,但没有bearer token 在这里我无法读取bearer token 我试图将其更改为:

    PlayersEndpoint.getEndpoint.zServerSecurityLogic{ case (token) => 
      //do smth with token 
     }.zServerLogic { case (playerId, query) => 
          //some logic to do...
        }

但它没有用。 我想阅读所有 3 个值并决定在检查令牌后做什么。 文档和示例非常糟糕,没有说明如何从貘读取令牌。 你知道我应该如何正确地做吗?

你可以试试这个:

import org.http4s.blaze.server.BlazeServerBuilder
import org.http4s.server.Router
import sttp.tapir.server.http4s.ztapir.ZHttp4sServerInterpreter
import sttp.tapir.ztapir._
import zio._
import zio.interop.catz._
import cats.implicits._


object TapirExample extends ZIOAppDefault {
  type Env = Any

  // fake type
  type PlayerId = Int
  type PlayerRequest = Long

  def authLogic(token: String): ZIO[Any, String, String] = {
    if (token != "secret") ZIO.fail("user not login")
    else ZIO.succeed(token)
  }

  val authEndpoint: ZPartialServerEndpoint[Any, String, String, Unit, String, Unit, Any] =
    endpoint
      .securityIn(auth.bearer[String]())
      .errorOut(stringBody)
      .zServerSecurityLogic(authLogic)

  val getEndpoint =
    authEndpoint
      .get
      .in("players" / path[PlayerId]("playerId"))
      .in(query[PlayerRequest]("query"))
      .out(stringBody)
      .serverLogic(token => queryTuple => getLogic(token, queryTuple._1, queryTuple._2))

  val getRoute =
    ZHttp4sServerInterpreter()
      .from(
        List(
          getEndpoint.widen[Env]
        )
      ).toRoutes

  def getLogic(token: String, playerId: PlayerId, request: PlayerRequest): ZIO[Any, Nothing, String] = {
    ZIO.succeed(
      s"""
        | token: $token
        | id: $playerId
        | request: $request
        |""".stripMargin)
  }

  override def run: ZIO[Any with ZIOAppArgs with Scope, Any, Any] = {


    val io = ZIO.runtime[Env].flatMap { _ =>
      for {
        _ <- ZIO.executor.flatMap(executor =>
          BlazeServerBuilder[ZIO[Env, Throwable, *]]
            .withExecutionContext(executor.asExecutionContext)
            .bindHttp(9090, "0.0.0.0")
            .withHttpApp(
              Router(
                "/" -> (
                  getRoute
                )
              ).orNotFound
            )
            .serve
            .compile
            .drain)
      } yield ()
    }

    io

  }
}

图书馆版本是

ThisBuild / version := "0.1.0-SNAPSHOT"

ThisBuild / scalaVersion := "2.13.8"

lazy val root = (project in file("."))
  .settings(
    name := "playground"
  )

val tapirVersion = "1.2.4"

val allDependency = Seq(
  "com.softwaremill.sttp.tapir" %% "tapir-http4s-server-zio" % tapirVersion,
  "org.http4s" %% "http4s-blaze-server"      % "0.23.13",
)

libraryDependencies ++= allDependency

addCompilerPlugin("org.typelevel" %% "kind-projector" % "0.13.2" cross CrossVersion.full)

curl测试

$ curl --location --request GET 'localhost:9090/players/233?query=334' \
--header 'Authorization: Bearer wrongtoken'
user not login

$ curl --location --request GET 'localhost:9090/players/233?query=334' \
--header 'Authorization: Bearer secret'

 token: secret
 id: 233
 request: 334

参考:

我没有 IDE 可以给你确切的代码,但我的想法是你的zServerSecurityLogic的返回可以在下面的zServerLogic中使用。

通常您会在zServerSecurityLogic中验证令牌并返回某种类型的User值,您可以将其用作zServerLogic中的输入。

但您也可以在安全逻辑中“什么都不做”,只传递令牌,以便它在主逻辑中可用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM