如何使用Akka HTTP进行身份验证

mat*_*r10 14 scala akka akka-http

寻找有关如何使用akka HTTP进行身份验证的良好解释.给出一条看起来像的路线

val route = 
  path("account") {
    authenticateBasic(realm = "some realm", myAuthenticator) { user =>
      get {
        encodeResponseWith(Deflate) {
          complete {
            //do something here
          }
        }
      }
    }
  }
Run Code Online (Sandbox Code Playgroud)

文档概述了一种方法,但是省略了执行实际认证的相关部分......

// backend entry points
def myAuthenticator: Authenticator[User] = ???
Run Code Online (Sandbox Code Playgroud)

我在哪里可以找到这种验证器的示例实现?我已经有了用于在给定用户名和密码的情况下对用户进行身份验证的逻辑,但我无法弄清楚如何从HTTP请求(或RequestContext)获取用户名/密码(或包含两者的令牌).

dk1*_*k14 10

Authenticator只是一个函数UserCredentials => Option[T],如果UserCredentials是(检查模式匹配)Provided有一些verifySecret(secret)方法,你需要安全地调用和返回Some(例如某些用户),如果成功,例如:

def myAuthenticator: Authenticator[User] = {
  case p@Provided(username) =>
    if(p.verifySecret(myGetSecret(username))) Some(username) else None
  case Missing => None //you can throw an exeption here to get customized response otherwise it will be regular `CredentialsMissing` message

}   
Run Code Online (Sandbox Code Playgroud)

myGetSecret是你的自定义函数,它获取用户名并返回你的秘密(例如密码),从数据库获取它.verifySecret将安全地比较(以避免计时攻击)提供密码和密码myGetSecret.通常,"秘密"是任何隐藏信息(如凭证或令牌的散列),但在基本身份验证的情况下,它只是从http标头中提取的普通密码.

如果您需要更多自定义方法 - 使用authenticateOrRejectWithChallengeHttpCredentials作为输入,那么您可以从那里提取提供的密码.

有关授权的更多信息,请参阅scaladocs.

  • @mattmar10 它接受带有用户名的字符串并返回带有普通密码的字符串。如果您有散列 - 不建议使用基本身份验证,因为它实际上不支持散列密码。正如在“PS”中所说,您可以使用“authenticateOrRejectWithChallenge”(参见scaladocs,也有来源——参见scaladoc 中的链接)。您可以从那里检索原始提供的密码并从中计算哈希值。使用 [secure_==](https://github.com/akka/akka/blob/release-2.3-dev/akka-http/src/main/scala/akka/http/scaladsl/server/directives/SecurityDirectives.scala #L212) 进行比较。 (2认同)