从http.Request获取客户端IP地址的正确方法

时间:2014-12-01 18:31:57

标签: http go ip

http.Request获取所有客户的IP地址的正确方法是什么?在PHP中,我应该检查很多variables。 Go上也一样吗?

我找到的是:

req.RemoteAddr

请求区分大小写吗?例如x-forwarded-forX-Forwarded-ForX-FORWARDED-FOR相同? (来自req.Header.Get("X-FORWARDED-FOR")

6 个答案:

答案 0 :(得分:61)

查看http.Request,您可以找到以下成员变量:

// HTTP defines that header names are case-insensitive.
// The request parser implements this by canonicalizing the
// name, making the first character and any characters
// following a hyphen uppercase and the rest lowercase.
//
// For client requests certain headers are automatically
// added and may override values in Header.
//
// See the documentation for the Request.Write method.
Header Header

// RemoteAddr allows HTTP servers and other software to record
// the network address that sent the request, usually for
// logging. This field is not filled in by ReadRequest and
// has no defined format. The HTTP server in this package
// sets RemoteAddr to an "IP:port" address before invoking a
// handler.
// This field is ignored by the HTTP client.
RemoteAddr string

您可以使用RemoteAddr获取远程客户端的IP地址和端口(格式为“IP:port”),这是原始请求者或最后一个代理的地址(例如,服务器前面的负载均衡器)。

这就是你所拥有的一切。

然后你可以研究一下不区分大小写的标题(根据上面的文档),这意味着你的所有例子都会起作用并产生相同的结果:

req.Header.Get("X-Forwarded-For") // capitalisation
req.Header.Get("x-forwarded-for") // doesn't
req.Header.Get("X-FORWARDED-FOR") // matter

这是因为内部http.Header.Get会为您规范化密钥。 (如果您想直接访问标题地图,而不是Get,则需要先使用http.CanonicalHeaderKey。)

最后,"X-Forwarded-For"可能是您想要查看的字段,以便获取有关客户端IP的更多信息。这在很大程度上取决于远程端使用的HTTP软件,因为客户端可以根据需要放置任何内容。另请注意,此字段的expected format是逗号+空格分隔的IP地址列表。您需要稍微解析它以获得您选择的单个IP(可能是列表中的第一个IP),例如:

// Assuming format is as expected
ips := strings.Split("10.0.0.1, 10.0.0.2, 10.0.0.3", ", ")
for _, ip := range ips {
    fmt.Println(ip)
}

将产生:

10.0.0.1
10.0.0.2
10.0.0.3

答案 1 :(得分:10)

这是一个完全有效的例子

beans.xml

答案 2 :(得分:2)

  

在PHP中,我应该检查很多变量。 Go上也一样吗?

这与没有与Go(或PHP)有关。它只取决于客户端,代理,负载均衡器或服务器发送的内容。根据您的环境获得您需要的那个。

http.Request.RemoteAddr包含远程IP地址。它可能是也可能不是您的实际客户。

  

请求区分大小写吗?例如x-forwarded-for与X-Forwarded-For和X-FORWARDED-FOR相同? (来自req.Header.Get(" X-FORWARDED-FOR"))

不,为什么不亲自尝试一下? http://play.golang.org/p/YMf_UBvDsH

答案 3 :(得分:1)

这就是我提出IP的方式

func ReadUserIP(r *http.Request) string {
    IPAddress := r.Header.Get("X-Real-Ip")
    if IPAddress == "" {
        IPAddress = r.Header.Get("X-Forwarded-For")
    }
    if IPAddress == "" {
        IPAddress = r.RemoteAddr
    }
    return IPAddress
}
  • X-Real-Ip-获取第一个真实IP(如果请求位于多个NAT源/负载均衡器之后)

  • X-Forwarded-For-如果出于某些原因X-Real-Ip为空并且不返回响应,请从X-Forwarded-For

  • 获取
  • 远程地址-不得已(通常是不可靠的,因为这可能是最后一个IP,或者如果它是对服务器的裸http请求,即没有负载均衡器)

答案 4 :(得分:1)

根据Mozilla MDN:“ X-Forwarded-For(XFF)标头是用于识别客户端原始IP地址的事实上的标准标头。
他们在他们的X-Forwarded-For文章中发布了明确的信息。

答案 5 :(得分:1)

使用 Cloudfront 时,客户端 IP 地址位于 x-original-forwarded-for 中。下面是一个 Javascript 示例。

function getIp(request) {
  const { headers, connection, socket } = request
  const connectionSocket = connection && connection.socket

  return (
    (headers && headers['x-original-forwarded-for']) ||
    (connection && connection.remoteAddress) ||
    (socket && socket.remoteAddress) ||
    (connectionSocket && connectionSocket.remoteAddress) ||
    null
  )
}