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

标签 http go ip

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

我找到的一个是:

req.RemoteAddr

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

最佳答案

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 将为您规范化 key 。 (如果你想直接访问header map,而不是通过Get,你需要先使用http.CanonicalHeaderKey。)

最后,"X-Forwarded-For" 可能是您想要查看的字段,以便获取有关客户端 IP 的更多信息。不过,这在很大程度上取决于远程端使用的 HTTP 软件,因为客户端可以根据需要在其中放置任何内容。另外,请注意 expected format该字段是逗号+空格分隔的 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

关于http - 从 http.Request 获取客户端 IP 地址的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27234861/

相关文章:

http - 可以加密通过 IIS 上的 HTTP 的身份验证(没有 SSL)吗?

java - spring 拦截器不向@RestController 服务添加 header

c# - 从控制台应用程序发布二进制数据

去模拟 Python 的 fileinput.input()?

ip - 如何防止 TOR Vidalia 更改我的 IP?

PHP 验证 - 将 http POST 值传递给第三方结帐

sql - 使用存储库模式时如何在 Go 中处理数据库连接?

google-app-engine - 在 App Engine 标准构建失败 : Your app is not on your GOPATH 上部署 go1.11

c# - 如何使用 BitShifting 将基于 int 的 IP 地址转换回字符串?

java - 将公共(public) IP 地址与用户提供的网络掩码进行匹配