加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – 在Akka-http中获取客户端IP

发布时间:2020-12-16 09:58:47 所属栏目:安全 来源:网络整理
导读:我正在尝试编写一个Akka HTTP微服务(akka版本2.4.11,Scala版本2.11.8,这两个版本在编写时都是最新版本),它们知道客户端服务的IP(即远程地址),我无法得到这个上班. 我可以创建并运行一个名为“你好
我正在尝试编写一个Akka HTTP微服务(akka版本2.4.11,Scala版本2.11.8,这两个版本在编写时都是最新版本),它们知道客户端服务的IP(即远程地址),我无法得到这个上班.

我可以创建并运行一个名为“你好!”的服务.使用这样的路线:

val routeHello: Route = path("SayHello") {
      get {
        entity(as[String]) {
          body => complete {
            HttpResponse(entity = HttpEntity("Hello!"))
          }
        }
      }
    }

我已经构建了一个与上面相似的路由,它被扩展,以便它知道客户端的IP地址.

我注意到我需要编辑application.conf文件并设置’remote-address-header = on’以启用添加包含客户端(远程)IP地址的Remote-Address标头.如果需要,我已经这样做了.

这是路线:

val routeHelloIp: Route = path("SayHelloIp") {
      get {
        // extractClientIp appears to be working as a filter
        // instead of an extractor - why?
        extractClientIp {
          clientIp => {
            entity(as[String]) {
              body => complete {
                HttpResponse(entity = HttpEntity("Hello!"))
              }
            }
          }
        }
      }
    }

但是,当我运行此路由时,我收到一条消息“无法找到所请求的资源.”.

看起来我在上面的例子中得到了Akka-http DSL语法糖错误.如果你能把我放在正确的道路上,我将不胜感激!

编辑:

我已经尝试了以下程序来回应Ramon的有用答案.不幸的是它没有编译,我无法看到我需要做什么才能使它编译.

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.Http.IncomingConnection
import java.net.InetSocketAddress
import akka.stream.ActorMaterializer
import akka.stream.scaladsl.Sink
import akka.http.scaladsl.server.Directives._
import java.net.InetSocketAddress


object TestHttp {
  def main(args: Array[String]) {

    implicit val system = ActorSystem("my-system")
    implicit val materializer = ActorMaterializer()

    // allow connections from any IP
    val interface = "0.0.0.0"

    //from the question
    def createRoute(address: InetSocketAddress) = path("SayHelloIp") {
      get {
        extractRequestEntity { entity =>
          entity(as[String]) { body =>
         complete(entity = s"Hello ${address.getAddress().getHostAddress()}")
          }
        }
      }
    }

    Http().bind(interface).runWith(Sink foreach { conn =>
  val address = conn.remoteAddress
   conn.handleWithAsyncHandler(createRoute(address))
    })
  }
}

我有以下build.sbt以确保使用最新版本的Scala和akka-http:

import sbt.Keys._

name := "Find my IP"

version := "1.0"

scalaVersion := "2.11.8"

resolvers ++= Seq(
  "Typesafe Repository" at "http://repo.typesafe.com/typesafe/releases/"
)

libraryDependencies ++= {
  Seq(
    "com.typesafe.akka" %% "akka-actor" % "2.4.11","com.typesafe.akka" %% "akka-stream" % "2.4.11","com.typesafe.akka" %% "akka-http-experimental" % "2.4.11","com.typesafe.akka" %% "akka-http-core" % "2.4.11"
  )
}

我得到以下编译时错误:

[error] /Users/tilopa/temp/akka-test/src/main/scala/Test.scala:24: akka.http.scaladsl.model.RequestEntity does not take parameters
[error]           entity(as[String]) { body =>
[error]                 ^
[error] /Users/tilopa/temp/akka-test/src/main/scala/Test.scala:25: reassignment to val
[error]             complete(entity = s"Hello ${address.getAddress().getHostAddress()}")
[error]                             ^
[error] two errors found
[error] (compile:compileIncremental) Compilation failed

解决方法

使用extractClientIp

extractClientIp不适合您,因为发件人尚未指定其中一个必需的标头字段.从documentation:

Provides the value of X-Forwarded-For,Remote-Address,or X-Real-IP
headers as an instance of RemoteAddress.

您只需在发件人中启用正确的设置:

The akka-http server engine adds the Remote-Address header to every
request automatically if the respective setting
akka.http.server.remote-address-header is set to on. Per default it is
set to off.

通用解决方案

如果你想让它适用于任何HttpRequest,而不仅仅是那些具有正确头设置的HttpRequest,那么你必须在HttpExt而不是bindAndHandle上使用bind方法:

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.Http.IncomingConnection

import java.net.InetSocketAddress

implicit val actorSystem : ActorSystem = ???
implicit val actorMat = ActorMaterializer()


//alow connections from any IP
val interface = "0.0.0.0"

//from the question
def createRoute(address : InetSocketAddress) = path("SayHelloIp") {
  get {
    extractRequestEntity { entity =>
      entity(as[String]) { body =>
        complete(entity = s"Hello ${address.getAddress().getHostAddress()}")
      }
    }
  }
}

Http().bind(interface).runWith(Sink foreach { conn =>
  val address =  conn.remoteAddress

  conn.handleWithAsyncHandler(createRoute(address))
})

编辑

如评论中所述:因为akka 10.0.13使用conn.handleWith.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读