开发(1)获取用户登录IP

参考链接:
Go获取IP地址
Golang实战:高效获取用户IP
exnet包获取客户端IP方法

1.从HTTP请求头获取IP

1.1 无代理情况

直接使用Request结构体里面的RemoteAddr

复制代码
type Request struct {
    ...
    // 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
    ...
}



package main
 
import (
	"fmt"
	"net/http"
)
 
func main() {
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		// 通过 RemoteAddr 获取客户端的 IP 地址和端口号
		ip, _, err := net.SplitHostPort(r.RemoteAddr)
		if err != nil {
			fmt.Println("Error extracting IP:", err)
			return
		}
 
		fmt.Fprintf(w, "Client IP: %s", ip)
	})
 
	// 启动 HTTP 服务器,监听在 8080 端口
	http.ListenAndServe(":8080", nil)
}

在这个例子中,r.RemoteAddr 包含了客户端的 IP 地址和端口号,使用 net.SplitHostPort 函数可以方便地从这个字符串中提取出 IP 地址。请注意,由于这个方法使用 TCP 连接的信息,所以对于某些代理服务器或负载均衡器,它可能只是代理服务器的 IP 地址,而不是实际客户端的 IP 地址。在这种情况下,可能需要查看 HTTP 头部中的相关字段以获取真实的客户端 IP 地址,具体看1.2小节。

1.2 反向代理、负载均衡、CDN存在情况

(1)

我们可以使用X-Forwarded-For头获取用户的真实IP地址。在经过反向代理或负载均衡服务器时,代理服务器会将用户的真实IP地址添加到HTTP请求的X-Forwarded-For头中。我们可以通过解析该头来获取用户的真实IP地址。下面是一个示例代码:

复制代码
go func getUserIP(r *http.Request) string { 
         ip := r.Header.Get("X-Forwarded-For") 
         return strings.Split(ip, ", ")[0] 
         } 

使用X-Forwarded-For头可以获取用户的真实IP地址,但是也存在一些问题。首先,X-Forwarded-For头可以被伪造或篡改,因此不能完全信任它。其次,某些代理服务器可能不会添加X-Forwarded-For头,导致无法获取真实IP地址。

(2)

另一种方法是通过解析HTTP请求的Header字段来获取用户的IP地址。这种方法相对准确且灵活,适用于各种网络环境。下面是一个示例代码:

复制代码
go func getUserIP(r *http.Request) string { ip := r.Header.Get("X-Real-IP") if ip == "" { ip = r.Header.Get("X-Forwarded-For") } if ip == "" { ip = r.RemoteAddr } return ip } 

使用Request Header可以兼容各种网络环境,并且可以获取用户的真实IP地址。但是需要注意,不同的HTTP服务器和代理服务器可能会使用不同的Header名称,因此需要根据实际情况进行设置。

2.使用第三方库

(1)Gin

在Gin中,客户端的IP地址可以通过请求的上下文(context)获取。

复制代码
package main

import (
    "github.com/gin-gonic/gin"
    "net/http"
)

func main() {
    router := gin.Default()

    router.GET("/visitor_ip", func(c *gin.Context) {
        clientIP := c.ClientIP()
        c.String(http.StatusOK, "Your IP: %s", clientIP)
    })

    router.Run()
}

当用户访问/visitor_ip端点时,IP地址会被捕获,并返回给他们。

但使用代理和负载均衡器时,c.ClientIP()方法会获得代理的IP,要解决这个问题,Gin尝试分析诸如X-Forwarded-For或者X-Real-IP等标头。

复制代码
// ClientIP implements one best effort algorithm to return the real client IP. 
// It calls c.RemoteIP() under the hood, to check if the remote IP is a trusted proxy or not. 
// If it is it will then try to parse the headers defined in Engine.RemoteIPHeaders (defaulting to [X-Forwarded-For, X-Real-Ip]). 
// If the headers are not syntactically valid OR the remote IP does not correspond to a trusted proxy, the remote IP (coming from Request.RemoteAddr) is returned.
func (c *Context) ClientIP() string


package main
 
import (
	"github.com/gin-gonic/gin"
	"net/http"
)
 
func main() {
	r := gin.Default()
 
	r.GET("/", func(c *gin.Context) {
		// 获取客户端的 IP 地址
		clientIP := c.ClientIP()
 
		c.String(http.StatusOK, "Client IP: %s", clientIP)
	})
 
	// 启动 Gin 服务器,监听在 8080 端口
	r.Run(":8080")
}

在这个例子中,c.ClientIP() 会自动处理不同的头部并返回客户端的 IP 地址。如果的应用程序部署在代理服务器或负载均衡器之后,确保这些设备正确地设置了 X-Forwarded-For 或 X-Real-IP 头部,以便正确获取客户端的 IP 地址。

(2)exnet包

exnet包提供了一系列方便的函数来处理IP地址相关操作。以下是一个使用exnet包获取用户真实IP的示例:

复制代码
package main

import (
	"fmt"
	"net/http"
	"github.com/chenzhuoyu/base64x"
	"github.com/valyala/fasthttp"
	"github.com/egoist/exnet"
)

func ClientIP(r *http.Request) string {
	ip := exnet.ClientPublicIP(r)
	if ip == "" {
		ip = exnet.RemoteIP(r)
	}
	return ip
}

func main() {
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		ip := ClientIP(r)
		fmt.Fprintf(w, "您的真实IP地址是: %s\n", ip)
	})

	fmt.Println("服务器启动,监听端口: 8080")
	http.ListenAndServe(":8080", nil)
}
相关推荐
wanhengidc5 小时前
云手机可以息屏挂手游吗?
运维·网络·安全·游戏·智能手机
一只小白菜~6 小时前
实战记录:H3C路由器IS-IS Level-1邻居建立与路由发布
运维·网络·计算机网络·智能路由器
kenwm6 小时前
家庭网络异常降速问题排查处理方案
网络·智能路由器
Web极客码6 小时前
在Ubuntu 20.04的服务器上查找的服务器的IP地址
服务器·tcp/ip·ubuntu
搬码临时工6 小时前
使用自定义固定公网URL地址远程访问公司内网OA办公系统,本地无需公网IP和专线让外网访问
网络·网络协议·tcp/ip
星马梦缘8 小时前
计算机网络6 第六章 应用层——解决“怎么发请求、怎么回响应”的问题(邮件整体传输流程)
网络·计算机网络·域名·ftp·dns·dhcp
@CLoudbays_Martin118 小时前
为什么动态视频业务内容不可以被CDN静态缓存?
java·运维·服务器·javascript·网络·python·php
东哥说-MES|从入门到精通10 小时前
Mazak MTF 2025制造未来参观总结
大数据·网络·人工智能·制造·智能制造·数字化
sheepwjl10 小时前
《嵌入式硬件(三):串口通信》
网络·嵌入式硬件·网络协议·串口通信
noravinsc10 小时前
RPC和HTTP的区别?
网络协议·http·rpc