基于Nginx 反向代理获取真实IP的问题详解
一、前言
前文Nginx解决WebApi跨域二次请求以及Vue单页面问题当中虽然解决了跨域问题带来的二次请求,但也产生了一个新的问题,就是如果需要获取用户IP的时候,获取的IP地址总是本机地址。
二、原因
由于Nginx反向代理后,在应用中取得的IP都是反向代理服务器的IP,取得的域名也是反向代理配置的Url的域名。
三、解决方案
解决该问题,需要在Nginx反向代理配置中添加一些配置信息,目的将客户端的真实IP和域名传递到应用程序中。同时,也要修改获取IP地址的方法。
但是需要注意的是,通过Nginx反向代理后,如果访问IP通过了几层代理,可能取得的IP地址是这种格式:clientIP,proxy1,proxy2。
如果需要将IP地址插入到数据库的话,需要做防止注入。因此要对上述的IP地址的格式进行截取。
3.1Nginx配置如下
server{ listen9461;#监听端口号 server_namelocalhost192.168.88.22;#访问地址 location/{ root项目路径;#例如:E:/Publish/xxx/; indexindex.html; #此处用于处理Vue、Angular、React使用H5的History时重写的问题 if(!-e$request_filename){ rewrite^(.*)/index.htmllast; break; } } #代理服务端接口 location/api{ proxy_passhttp://localhost:9460/api;#代理接口地址 #Host配置以及域名传递 proxy_set_headerHost$host; proxy_set_headerX-Real-IP$remote_addr; proxy_set_headerREMOTE-HOST$remote_addr; proxy_set_headerX-Forwarded-For$proxy_add_x_forwarded_for; } }
3.2C#代码获取真实IP方法
#regionIp(客户端IP地址) //////客户端IP地址 /// publicstaticstringIp { get { varresult=string.Empty; if(HttpContext.Current!=null) { result=GetWebClientIp(); } if(string.IsNullOrWhiteSpace(result)) { result=GetLanIp(); } returnresult; } } //////获取Web客户端的IP /// ///privatestaticstringGetWebClientIp() { varip=GetWebProxyRealIp()??GetWebRemoteIp(); foreach(varhostAddressinDns.GetHostAddresses(ip)) { if(hostAddress.AddressFamily==AddressFamily.InterNetwork) { returnhostAddress.ToString(); } } returnstring.Empty; } /// ///获取Web远程IP /// ///privatestaticstringGetWebRemoteIp() { try { returnHttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"]?? HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"]??""; } catch(Exceptione) { returnstring.Empty; } } /// ///获取Web代理真实IP /// ///privatestaticstringGetWebProxyRealIp() { varrequest=HttpContext.Current.Request; stringip=request.Headers.Get("x-forwarded-for"); if(string.IsNullOrEmpty(ip)||string.Equals("unknown",ip,StringComparison.OrdinalIgnoreCase)) { ip=request.Headers.Get("Proxy-Client-IP"); } if(string.IsNullOrEmpty(ip)||string.Equals("unknown",ip,StringComparison.OrdinalIgnoreCase)) { ip=request.Headers.Get("WL-Proxy-Client-IP"); } if(string.IsNullOrEmpty(ip)||string.Equals("unknown",ip,StringComparison.OrdinalIgnoreCase)) { ip=request.UserHostAddress; } if(string.IsNullOrEmpty(ip)) { returnstring.Empty; } //可能存在如下格式:X-Forwarded-For:client,proxy1,proxy2 if(ip.Contains(",")) { //如果存在多个反向代理,获得的IP是一个用逗号分隔的IP集合,取第一个 //X-Forwarded-For:client第一个 string[]ips=ip.Split(newstring[1]{","},StringSplitOptions.RemoveEmptyEntries); vari=0; for(i=0;i ///判断IP地址是否为内网IP地址 /// /// IP地址 /// privatestaticboolIsInnerIp(stringip) { boolisInnerIp=false; ulongipNum=Ip2Ulong(ip); /** *私有IP *A类:10.0.0.0-10.255.255.255 *B类:172.16.0.0-172.31.255.255 *C类:192.168.0.0-192.168.255.255 *当然,还有127这个网段是环回地址 */ ulongaBegin=Ip2Ulong("10.0.0.0"); ulongaEnd=Ip2Ulong("10.255.255.255"); ulongbBegin=Ip2Ulong("172.16.0.0"); ulongbEnd=Ip2Ulong("10.31.255.255"); ulongcBegin=Ip2Ulong("192.168.0.0"); ulongcEnd=Ip2Ulong("192.168.255.255"); isInnerIp=IsInner(ipNum,aBegin,aEnd)||IsInner(ipNum,bBegin,bEnd)||IsInner(ipNum,cBegin,cEnd)|| ip.Equals("127.0.0.1"); returnisInnerIp; } /// ///将IP地址转换为Long型数字 /// ///IP地址 /// privatestaticulongIp2Ulong(stringip) { byte[]bytes=IPAddress.Parse(ip).GetAddressBytes(); ulongret=0; foreach(varbinbytes) { ret<<=8; ret|=b; } returnret; } /// ///判断用户IP地址转换为Long型后是否在内网IP地址所在范围 /// ///用户IP /// 开始范围 /// 结束范围 /// privatestaticboolIsInner(ulonguserIp,ulongbegin,ulongend) { return(userIp>=begin)&&(userIp<=end); } /// ///获取局域网IP /// ///privatestaticstringGetLanIp() { foreach(varhostAddressinDns.GetHostAddresses(Dns.GetHostName())) { if(hostAddress.AddressFamily==AddressFamily.InterNetwork) { returnhostAddress.ToString(); } } returnstring.Empty; } #endregion
以上这篇基于Nginx反向代理获取真实IP的问题详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。