在Play Framework(Scala)中限制特定IP访问

4
2个回答

6
将要限制的IP地址添加到application.conf文件中。
myapp.ipwhitelist = ["192.168.1.1", ...]

接下来创建一个全局过滤器,用于应用于每个传入请求,例如:

import scala.collection.JavaConverters._
import play.api.libs.concurrent.Execution.Implicits._
import play.api.libs.iteratee.Iteratee
import play.api.Play.current
import play.api.mvc._

object IPFilter extends EssentialFilter {
  def apply(nextFilter: EssentialAction) = new EssentialAction {
    def apply(requestHeader: RequestHeader) = {
      // read the IPs as a Scala Seq (converting from the Java list)
      val ips: Seq[String] = current.configuration.getStringList("myapp.ipwhitelist")
            .map(_.asScala).getOrElse(Seq.empty)

      // Check we've got an allowed IP, otherwise ignore the
      // request body and immediately return a forbidden.
      if (ips.contains(requestHeader.remoteAddress)) nextFilter(requestHeader)
      else Iteratee.ignore[Array[Byte]]
        .map(_ => Results.Forbidden(s"Bad IP! ${requestHeader.remoteAddress}"))
    }
  }
}

然后在你的应用程序全局对象中启用它:

object Global extends WithFilters(IPFilter) with GlobalSettings

如果您需要更多的灵活性,您可以使用相同的逻辑,但是使用Action composition而不是全局过滤器。

1
在启动时将IP地址读入lazy val可能是个好主意,除非你真的需要在每个请求上重新从文件中读取白名单。 - millhouse
如果启用了 play.filters.hosts,这个方法就行不通了,对吧? - Todor Kolev
在Play 2.6中,我使用了Accumulator.done(Results.Forbidden)而不是Iteratee。 - Ikrom

0

我认为生产环境需要更多的HTTP配置(公共,接受任何HTTP请求),应该使用HTTP前端服务来适当地将请求分配到Play。

至于我是否可以将一个子域名映射到多个Play框架入口点,使用像Apache、Nginx或Varnish这样的服务来配置HTTP访问控制列表(ACL)是有优势的。例如在Varnish中:

acl my-acl {
    "an-authorized-host";
    "1.2.3.4";
}

# Then ...
if (!client.ip ~ my-acl) {
    error 405 "Not allowed.";
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接