如何在身份验证指令中包装我的路由,然后为我的路由访问提供自定义类的可见性



我的API客户端将在头或查询字符串中传递会话令牌,如:

Http Header with key/value like MyApp-Token abc123
Url:
https://api.example.com/v1/board?authToken=abc123
val secureRoutes =
authenticateToken() { authenticatedContext =>
path("board") {
get {
complete(s"board#index route ${authenticatedContext.user.username}")
}
}
}

是否有内置指令可以为我做到这一点,或者我是否必须以某种方式创建自己的自定义指令,该指令将首先在HTTP标头中查找,如果没有,则查看键authToken处是否有查询字符串值?

如果我必须创建一个自定义指令,有什么可以借鉴的例子吗?

我知道我可以使用内置指令获得HTTP标头:

headerValueByName("x-authToken") { authToken =>
get {
complete(s"board#index route 2.1 $authToken")
}
}

还有一个指令可以从查询字符串中获取值:

parameter("authToken") { authToken => 
...
}

我如何将两者结合起来,然后在内部进行数据库调用,然后不返回authToken,而是返回一个自定义事例类,该类将包含我刚刚从数据库加载的数据,如:

case class AuthenticatedContext(authToken: String, user: User, ...)

我们总是可以构造一个自定义指令或组成如下所示的指令:

case class AuthenticatedContext(authToken: String)
def validateTokenAndGetAuthContext(token: String): Future[AuthenticatedContext] = {
Future.successful(AuthenticatedContext(token))
}
val authToken: Directive1[AuthenticatedContext] = optionalHeaderValueByName("authToken").flatMap {
case Some(token) =>
onComplete(validateTokenAndGetAuthContext(token)).flatMap {
case Failure(_) => reject(AuthorizationFailedRejection)
case Success(value) => provide(value)
}
case None =>
parameter("authToken".optional).flatMap {
case Some(token) =>
onComplete(validateTokenAndGetAuthContext(token)).flatMap {
case Failure(_) => reject(AuthorizationFailedRejection)
case Success(value) => provide(value)
}
case None => reject(AuthorizationFailedRejection)
}
}

它是使用HeaderDirectives、ParameterDirectives和FuturesDirectives构建的。

最新更新