-
Notifications
You must be signed in to change notification settings - Fork 3
/
clientIP.go
47 lines (41 loc) · 1.77 KB
/
clientIP.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package httpKit
import (
"github.com/duke-git/lancet/v2/netutil"
"github.com/richelieu-yang/chimera/v2/src/core/errorKit"
"net"
"net/http"
"strings"
)
var (
// GetRequestPublicIp 获取http请求ip.
GetRequestPublicIp func(req *http.Request) string = netutil.GetRequestPublicIp
)
// GetClientIP Deprecated: Use GetRequestPublicIp instead.
/*
!!!: 请注意,恶意用户可以创建伪造的 X-REAL-IP 和 X-FORWARDED-FOR 标头。因此,在处理这些头部信息时需要谨慎。如果可能,应该使用一种方法来验证IP地址的真实性。
流程:
(1) 这个函数首先尝试获取X-Real-IP头部信息,如果这个头部信息存在并且是一个有效的IP地址,那么就返回这个IP。
(2) 如果X-Real-IP头部信息不存在或者不是一个有效的IP地址,那么函数会尝试获取X-Forwarded-For头部信息,这个头部信息包含了一个IP地址列表,每个经过的代理服务器都会添加一个IP。
(3) 如果X-Forwarded-For头部信息中存在有效的IP地址,那么就返回这个IP。
(4) 如果以上两个头部信息都不存在有效的IP地址,那么函数会尝试获取RemoteAddr,这个是Web服务器从其接收连接并将响应发送到的实际物理IP地址。
*/
func GetClientIP(r *http.Request) (string, error) {
ip := r.Header.Get("X-Real-IP")
if net.ParseIP(ip) != nil {
return ip, nil
}
ip = r.Header.Get("X-Forwarded-For")
for _, i := range strings.Split(ip, ",") {
if net.ParseIP(i) != nil {
return i, nil
}
}
host, _, err := net.SplitHostPort(r.RemoteAddr)
if err != nil {
return "", errorKit.Wrap(err, "Fail to get client ip with RemoteAddr(%s)", r.RemoteAddr)
}
if net.ParseIP(host) != nil {
return host, nil
}
return "", errorKit.New("Fail to get client ip with host(%s)", host)
}