• 关于使用代理后,后端获取客户端IP中遇到的问题(比如.NetCore、Vue、Nginx)


      首先,我们有多种方式获取本地IP地址,比如:.net core获取本地Ip地址的方法 ,这种方式与项目类型无关。

      如果后端项目是一个web项目,我们还可以通过HttpContext来获取后端项目所在服务器的本地IP,而且还能获取客户端的IP地址:  

        var connection = HttpContext.Connection;
    
        //客户端IP地址(v4和v6)
        var remoteIpAddressIPv4 = connection.RemoteIpAddress?.MapToIPv4()?.ToString();
        var remoteIpAddressIPv6 = connection.RemoteIpAddress?.MapToIPv6()?.ToString();
        //服务端本地IP地址(v4和v6)
        var localIpAddressIPv4 = connection.LocalIpAddress?.MapToIPv4()?.ToString();
        var localIpAddressIPv6 = connection.LocalIpAddress?.MapToIPv6()?.ToString();

      但是现在的web项目应该很少有直接面向客户端使用的吧,都是中间或多或少有几个网关或者代理,比如使用nginx:  

        location / {        
            proxy_pass http://localhost:5000;
        }

      或者前端Vue开发时使用了使用http-proxy-middleware做代理:  

      devServer: {
        proxy: {
          '/api': {
            target: process.env.VUE_APP_API_BASE_URL,
            ws: false,
            changeOrigin: true,
            pathRewrite: {
              '^/api': '' // 需要rewrite的,
            }
          }
        }
      }

      那么问题来了,一旦客户端的请求被代理了,那么上面获取获取客户端IP地址的方式就不准确了,因为请求被代理转发了,这样它获取的就是代理端的IP,而不是客户端的IP,那么怎么解决这个问题呢?

      这就要说到两个特殊的请求头了:X-Real-IP 与 X-Forwarded-For

      X-Real-IP:表示真实的IP,但是实际上,它表示多级代理中最后一个代理的IP,可惜的是,它只是被一些组织机构认可,貌似并没有一个标准的规范。

      X-Forwarded-For:表示请求从客户端发起后所经过的所有代理的IP地址,这些IP地址使用英文逗号+空格(, )进行分隔,其中第一个就是客户端的IP地址,形如:  

        X-Forwarded-For: 192.168.128.111, 192.168.128.112, 192.168.128.113

      那么解决这个问题的关键就是在代理转发请求时,我们需要给转发的请求加上这个X-Forwarded-For请求头!X-Real-IP可以添加,也可以不添加,只是后端读取不一样。

      如果使用的是Nginx:  

        location / {
            proxy_pass http://localhost:5000;
            proxy_http_version 1.1;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    
            # 如果是代理websocket,还需要下面两个
            # proxy_set_header Upgrade $http_upgrade;
            # proxy_set_header Connection "upgrade";
        }

      $remote_addr表示上一级代理的IP,如果上一级是客户端,那么它就表示客户端的IP,$proxy_add_x_forwarded_for表示将$remote_addr追加到上一级代理的X-Forwarded-For请求头中,并将追加后的内容作为X-Forwarded-For请求头转发到下一级,这样客户端的IP就一级一级的转发到了服务端

      如果是Vue开发过程中使用了http-proxy-middleware做代理:  

      devServer: {
        proxy: {
          '/api': { //如果是API接口
            target: process.env.VUE_APP_API_BASE_URL,
            ws: false,
            changeOrigin: true,
            pathRewrite: {
              '^/api': '' // 需要rewrite的,
            },
            onProxyReq(proxyReq, req, res) {
              //req中默认是携带有x-forwarded-for请求头的,只需添加X-Real-IP请求头
              req.headers['X-Real-IP'] = req.ip
            }
          },
          '/socket': { //如果是websocket
            target: process.env.VUE_APP_SOCKET_BASE_URL,
            ws: true,
            changeOrigin: true,
            onProxyReqWs(proxyReq, req, socket, options, head) {
              //req中默认是携带有x-forwarded-for请求头的,只需添加X-Real-IP请求头
              req.headers['X-Real-IP'] = req.ip
            }
          }
        }
      }

      这里onProxyReq是代理普通http接口前会触发的事件,onProxyReqWs则是代理websocket前会触发的事件

      接着后端获取IP可以从下面的规则中获取:  

        string ip = HttpContext.Request.Headers["X-Real-IP"].ToString();
        if (string.IsNullOrEmpty(ip))
        {
            string ips = HttpContext.Request.Headers["X-Forwarded-For"].ToString();
            ip = ips.Split(new string[] { ", " }, StringSplitOptions.RemoveEmptyEntries).FirstOrDefault();
            if (string.IsNullOrEmpty(ip))
            {
                ip = HttpContext.Connection.RemoteIpAddress?.MapToIPv4()?.ToString();
            }
        }
  • 相关阅读:
    foxmail邮箱在代理环境下不能使用解决方法。
    Win7下IE8无法打开https类型的网站解决方法笔记
    重新注册IE组件
    Web开发者的六个代码调试平台
    仿Material UI框架的动画特效
    JS几种数组遍历方式以及性能分析对比
    js 函数提升和变量提升
    彻底掌握this,call,apply
    深入理解requestAnimationFrame
    基于iscroll.js实现下拉刷新和上拉加载特效
  • 原文地址:https://www.cnblogs.com/shanfeng1000/p/15911031.html
Copyright © 2020-2023  润新知