golang,go,博客,开源,编程

gin中间件,实现ip白名单

Published on with 0 views and 0 comments

Gin 中实现 IP 白名单功能可以通过编写自定义中间件来过滤允许的 IP 地址。只有当请求的 IP 地址在白名单中时,才允许访问,否则返回拒绝访问的响应。

1. 实现 IP 白名单中间件

以下是一个简单的中间件示例,它会检查请求的 IP 地址是否在允许的白名单中:

package main

import (
	"net/http"
	"strings"

	"github.com/gin-gonic/gin"
)

// 白名单中间件
func IPWhitelistMiddleware(allowedIPs []string) gin.HandlerFunc {
	return func(c *gin.Context) {
		// 获取请求的 IP 地址
		clientIP := c.ClientIP()

		// 检查 IP 是否在白名单中
		allowed := false
		for _, ip := range allowedIPs {
			if ip == clientIP {
				allowed = true
				break
			}
		}

		if !allowed {
			// 如果 IP 不在白名单中,返回 403 禁止访问
			c.JSON(http.StatusForbidden, gin.H{
				"message": "Forbidden: Your IP is not in the whitelist",
			})
			c.Abort() // 终止请求
			return
		}

		// 如果 IP 在白名单中,继续处理请求
		c.Next()
	}
}

func main() {
	// 定义允许的 IP 地址列表
	allowedIPs := []string{
		"127.0.0.1", // 本地 IP
		"192.168.1.100", // 示例 IP
	}

	// 创建 Gin 实例
	r := gin.Default()

	// 应用 IP 白名单中间件
	r.Use(IPWhitelistMiddleware(allowedIPs))

	// 示例路由
	r.GET("/hello", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"message": "Hello, your IP is allowed!",
		})
	})

	// 启动服务器
	r.Run(":8080")
}

2. 代码解析

  • IPWhitelistMiddleware
    • 这是一个自定义中间件,用于检查请求的 IP 是否在白名单中。它接受一个 allowedIPs 切片,该切片包含了所有允许访问的 IP 地址。
    • c.ClientIP() 用于获取客户端的 IP 地址。在本地开发时,它通常会返回 127.0.0.1,如果是在生产环境中,它会返回实际的请求源 IP 地址(例如,来自负载均衡器后的真实 IP)。
    • 如果请求的 IP 不在白名单中,中间件会返回 403 禁止访问的响应,并终止请求的后续处理(c.Abort())。如果 IP 在白名单中,c.Next() 会继续处理请求。
  • allowedIPs 列表
    • 你可以根据实际需求设置允许的 IP 地址。这个列表可以在配置文件中加载,或者根据部署环境动态获取。

3. 启动应用

运行上述程序后,当你访问 http://localhost:8080/hello 时,只有来自 127.0.0.1192.168.1.100 的请求能够访问该路由,其他 IP 的请求将会被拒绝并返回 403 错误。

示例:

  1. 允许 IP 请求(来自 127.0.0.1192.168.1.100):

    curl http://127.0.0.1:8080/hello
    

    响应:

    {
      "message": "Hello, your IP is allowed!"
    }
    
  2. 不允许的 IP 请求(例如,来自 10.0.0.1):

    curl http://10.0.0.1:8080/hello
    

    响应:

    {
      "message": "Forbidden: Your IP is not in the whitelist"
    }
    

4. 扩展功能

  • 支持 CIDR 格式的 IP 范围:如果需要支持 IP 范围(如 192.168.1.0/24),你可以使用 Go 的 net 包来解析 CIDR 格式,并检查请求 IP 是否落在指定的网络范围内。
  • 动态修改白名单:可以将白名单存储在外部配置源(如数据库、文件、Redis 等)中,并允许动态修改白名单,而无需重启应用。

5. 支持外部 IP(例如反向代理)

如果你的应用部署在反向代理后(如 Nginx 或 Cloudflare),c.ClientIP() 可能会返回代理服务器的 IP,而不是实际的客户端 IP。在这种情况下,你需要从请求头中获取真实的客户端 IP,通常是 X-Forwarded-ForX-Real-IP 头。

修改获取 IP 的代码如下:

// 获取客户端真实 IP(从 X-Forwarded-For 或 X-Real-IP 头)
func getClientIP(c *gin.Context) string {
	// 获取 X-Forwarded-For 头,通常包含了代理链的 IP 地址
	xfHeader := c.GetHeader("X-Forwarded-For")
	if xfHeader != "" {
		// 返回第一个 IP 地址(客户端真实 IP)
		ips := strings.Split(xfHeader, ",")
		return strings.TrimSpace(ips[0])
	}
	// 如果没有 X-Forwarded-For 头,返回直接请求的 IP
	return c.ClientIP()
}

总结

通过 Gin 中间件实现 IP 白名单功能,能有效地控制哪些 IP 地址可以访问你的应用。通过配置白名单,你能够增强应用的安全性,防止未授权的访问。这个中间件可以扩展支持动态白名单、IP 范围、以及反向代理配置等复杂需求。


标题:gin中间件,实现ip白名单
作者:mooncakeee
地址:http://blog.dd95828.com/articles/2025/01/07/1736218218267.html
联系:scotttu@163.com