C#获取真实IP地址(IP转为长整形、判断是否内网IP的方法)
作者:junjie 发布时间:2022-01-31 08:50:06
标签:C#,IP地址
今天查看登录日志,发现http_x_forwarded_for获取到的ip地址有些是内网ip地址,有些则是公网和内网ip地址一起获取到,用逗号分隔开,日志截图如下:
之前获取ip地址的C#代码如下:
/// <summary>
/// C#获取客户端真实IP地址
/// </summary>
/// <returns></returns>
public static string GetIP()
{
string ip = HttpContext.Current.Request.ServerVariables["http_x_forwarded_for"];
if (UserCheck.IsNull(ip)) ip = HttpContext.Current.Request.ServerVariables["remote_addr"];
return ip;
}
看来http_x_forwarded_for应该是被其他软件或者ISP修改过了,导致http_x_forwarded_for得不到真实的代理ip地址。之前登陆日志是要判断ip地址是否在允许的ip段内的,这样导致无法登陆系统。最后修改代码如下,增加判断是否为内网或者私有地址,是否符合ipv4的地址规格,不符合还是使用remote_addr来获取客户端的ip地址。
比较安全的获取真实地址的实现代码:
/// <summary>
/// C#将IP地址转为长整形
/// </summary>
/// <param name="ip"></param>
/// <returns></returns>
public static long IpToNumber(string ip)
{
string[] arr = ip.Split('.');
return 256 * 256 * 256 * long.Parse(arr[0]) + 256 * 256 * long.Parse(arr[1]) + 256 * long.Parse(arr[2]) + long.Parse(arr[3]);
}
/// <summary>
/// C#判断IP地址是否为私有/内网ip地址
/// </summary>
/// <param name="ip"></param>
/// <returns></returns>
public static bool IsPrivateIp(string ip)
{
long ABegin = IpToNumber("10.0.0.0"), AEnd = IpToNumber("10.255.255.255"),//A类私有IP地址
BBegin = IpToNumber("172.16.0.0"), BEnd = IpToNumber("172.31.255.255"),//'B类私有IP地址
CBegin = IpToNumber("192.168.0.0"), CEnd = IpToNumber("192.168.255.255"),//'C类私有IP地址
IpNum = IpToNumber(ip);
return (ABegin <= IpNum && IpNum <= AEnd) || (BBegin <= IpNum && IpNum <= BEnd) || (CBegin <= IpNum && IpNum <= CEnd);
}
/// <summary>
/// C#获取真实IP地址
/// </summary>
/// <returns></returns>
public static string GetIP()
{
string ip = HttpContext.Current.Request.ServerVariables["http_x_forwarded_for"];
if (UserCheck.IsNull(ip)) ip = HttpContext.Current.Request.ServerVariables["remote_addr"];
else//代理ip地址有内容,判断是否符合ipv4地址或者是否为内网地址
{
ip = ip.Trim().Replace(" ", "");
if (!Regex.IsMatch(ip, @"^\d+(\.\d+){3}$") || IsPrivateIp(ip))
ip = HttpContext.Current.Request.ServerVariables["remote_addr"];//不符合规则或者内网/私有地址使用remote_addr代替
}
return ip;
}
2014-07-02更新:原来是 cdn加速的问题,cdn加速后,由于先判断http_x_forwarded_for,http_x_forwarded_for是随便可以伪造的,放置任何内容的,所以下图出现的ip地址中会有内网地址或者出现2个ip地址的问题。所以获取http_x_forwarded_for内容时需要 split下获取第一个项。


猜你喜欢
- 这篇文章主要介绍了Jenkins Host key verification failed问题解决,文中通过示例代码介绍的非常详细,对大家的
- 本文实例讲述了Android内容提供者ContentProvider用法。分享给大家供大家参考,具体如下:PersonContentProv
- 1 场景调用多个平级服务,按照服务优先级返回第一个有效数据。具体case:一个页面可能有很多的弹窗,弹窗之间又有优先级。每次只需要返回第一个
- aop,即面向切面编程,面向切面编程的目标就是分离关注点,比如:一个骑士只需要关注守护安全,或者远征,而骑士辉煌一生的事迹由谁来记录和歌颂呢
- @PathVariable接收两个参数首先@PathVariable无法接收对象,但是可以接收多个值var data = obj.data;
- 1、多态性多态性是面向对象的最后一个特征,它本身主要分为两个方面:方法的多态性:重载与覆写1 重载:同一个方法名称,根据参数类型以及个数完成
- 本文实例为大家分享了使用PageHelper插件实现Service层分页的具体代码,供大家参考,具体内容如下使用场景:平时分页我们可以直接使
- 概要笔者近期做到对天气预报JSON数据解析,在此小记。天气预报接口:http://wthrcdn.etouch.cn/weather_min
- 概述在使用maven进行Java项目的开发过程中,难免会有些公共的私有库,这些库是不太方便放到中央仓库的,可以通过Nexus搭建一个私有仓库
- 下标到指针之间和转换以下的程序做了什么。#include <stdio.h> int main() { int a
- 这两种方式也是大家在日常编码工作当中用的比较多的判断方式、之前在使用的时候也没太关注两者在比较不同类型的时候存在哪些区别今天就和大家一起深入
- 一、增删改1、增加<!-- 添加用户--><insert id="saveUser" paramete
- 一、为什么要编码不知道大家有没有想过一个问题,那就是为什么要编码?我们能不能不编码?要回答这个问题必须要回到计算机是如何表示我们人类能够理解
- 在Android程序开发中我们经常遇到四种数据存储方式,每种存储方式都各有不同;以下我分别列举了Android开发中的不同存储方式的特点一,
- 学习spring依赖注入的时候碰到这个坑,折腾了许久,记录一下以防其他小伙伴入坑!该异常主要原因是因为JDK与Spring版本不一致。要么更
- 做tcp网络编程,要解析一批批的数据,可是数据是通过Socket连接的InputStream一次次读取的,读取到的不是需要转换的对象,而是要
- 原则:1、垃圾回收机制,维护引用信息不维护指针信息2、引用类型的实例化对象在生存期内由垃圾回收机制处理,可能移动内存3、当一个类的实例化对象
- 前言在使用Mybatis-Plus新增的时候,我们往往想要id随着数据库自增,但是如果不是我们指定id为auto(自增)的话,会通过算法算出
- 这篇文章主要介绍了Spring 事件Application Event原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定
- Unity脚本自动添加头部注释就是创建.cs文件时自动添加作者名,创建时间,文件名等看示例,我们在Unity的project面板下先创建一个