【go系列】使用gin实现ip拦截器

auth.go

/**
* @Description: ip拦截器
* @Author: Walker
* @Date: 2021/4/16
 */
package auth

import (
	"github.com/gin-gonic/gin"
	"net/http"
	ip2 "wxtokenmicroservice/service/ip"
	service "wxtokenmicroservice/utils/ip"
)

//返回类型:HandlerFunc
func IpAuthorize() gin.HandlerFunc {
	return func(c *gin.Context) {
        //获取ip
		ip := service.GetRealIp(c.Request)
        //查询数据库是否存在该ip
		res := ip2.IfExistsIp(ip)
		if res == 1 {
			// 验证通过,会继续访问下一个中间件
			c.Next()
		} else {
			// 验证不通过,不再调用后续的函数处理
			c.Abort()
			c.JSON(http.StatusUnauthorized, gin.H{
				"code":    401,
				"message": "访问未授权",
				"data":    res,
			})
			// return可省略, 只要前面执行Abort()就可以让后面的handler函数不再执行
			return
		}
	}
}

获取ip

package service

import (
	"net"
	"net/http"
	"strconv"
	"strings"
)

// ClientIP 尽最大努力实现获取客户端 IP 的算法。
// 解析 X-Real-IP 和 X-Forwarded-For 以便于反向代理(nginx 或 haproxy)可以正常工作。
func ClientIp(r *http.Request) string {
	xForwardedFor := r.Header.Get("X-Forwarded-For")
	ip := strings.TrimSpace(strings.Split(xForwardedFor, ",")[0])
	if ip != "" {
		return ip
	}

	ip = strings.TrimSpace(r.Header.Get("X-Real-Ip"))
	if ip != "" {
		return ip
	}

	ip, _, err := net.SplitHostPort(strings.TrimSpace(r.RemoteAddr))
	if err == nil {
		return ip
	}
	return ""
}

// ClientPublicIP 尽最大努力实现获取客户端公网 IP 的算法。
// 解析 X-Real-IP 和 X-Forwarded-For 以便于反向代理(nginx 或 haproxy)可以正常工作。
func ClientPublicIP(r *http.Request) string {
	var ip string
	for _, ip = range strings.Split(r.Header.Get("X-Forwarded-For"), ",") {
		ip = strings.TrimSpace(ip)
		if ip != "" && !IsLocalIp(ip) {
			return ip
		}
	}

	ip = strings.TrimSpace(r.Header.Get("X-Real-Ip"))
	if ip != "" && !IsLocalIp(ip) {
		return ip
	}

	if ip, _, err := net.SplitHostPort(strings.TrimSpace(r.RemoteAddr)); err == nil {
		if !IsLocalIp(ip) {
			return ip
		}
	}

	return ""
}

func IsLocalIp(ip string) bool {
	/*
		局域网(intranet)的IP地址范围包括:

		10.0.0.0/8--10.0.0.0~10.255.255.255(A类)

		172.16.0.0/12-172.16.0.0-172.31.255.255(B类)

		192.168.0.0/16--192.168.0.0~192.168.255.255(C类)
	*/
	ipAddr := strings.Split(ip, ".")

	if strings.EqualFold(ipAddr[0], "10") {
		return true
	} else if strings.EqualFold(ipAddr[0], "172") {
		addr, _ := strconv.Atoi(ipAddr[1])
		if addr >= 16 && addr < 31 {
			return true
		}
	} else if strings.EqualFold(ipAddr[0], "192") && strings.EqualFold(ipAddr[1], "168") {
		return true
	}
	return false
}

func GetRealIp(r *http.Request) string {
	ip := ClientPublicIP(r)
	if ip == "" {
		ip = ClientIp(r)
	}
	return ip
}

router.go

func InitRouter() *gin.Engine {
	router := gin.Default()
	v1 := router.Group("/v1")
	{
		/*不需要进行ip拦截的api*/
		//这个api不会被拦截
		router.POST("/v1/corp/add", corp.AddCorpCode)
	}


	
	router.Use(auth.IpAuthorize())  //分界线,开启认证
	/*需要进行ip拦截的api*/
	{
		//这个api就会被拦截
		v1.POST("/corp/delete", corp.DelCorpCode)
	}

	

	return router
}

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WalkerShen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值