IP 地址验证

发布于 2024-10-19 01:54:15 字数 1042 浏览 7 评论 0原文

我正在重构我的代码并想使用 < code>IPAddress.TryParse 方法来验证字符串是否是有效的 IPv4 地址,而不是使用正则表达式:

public static bool IsIPv4(string value)
{
    IPAddress address;

    if (IPAddress.TryParse(value, out address))
    {
        if (address.AddressFamily == AddressFamily.InterNetwork)
        {
            return true;
        }
    }

    return false;
}

我的单元测试现在失败,因为这些输入值返回 true 并且被解析为以下 IPAddress 对象:

value = "0.0.0.0"      ->  address = {0.0.0.0}
value = "255.255.255"  ->  address = {255.255.0.255}
value = "65536"        ->  address = {0.1.0.0}

这有意义吗?我可以看到 0.0.0.0从技术上讲, 是一个有效的 IPv4 地址,即使用户输入该地址没有任何意义。另外两个呢?为什么它们以原来的方式转换?我是否应该将它们视为有效,即使它对用户来说可能不透明,他们可能只是忘记输入句点(65536 而不是 6.5 .5.36)。

非常感谢任何帮助。

I'm refactoring my code and wanted to use the IPAddress.TryParse method to validate if a string is a valid IPv4 address instead of using regular expressions:

public static bool IsIPv4(string value)
{
    IPAddress address;

    if (IPAddress.TryParse(value, out address))
    {
        if (address.AddressFamily == AddressFamily.InterNetwork)
        {
            return true;
        }
    }

    return false;
}

My unit test is now failing because these input values return true and get parsed to the following IPAddress objects:

value = "0.0.0.0"      ->  address = {0.0.0.0}
value = "255.255.255"  ->  address = {255.255.0.255}
value = "65536"        ->  address = {0.1.0.0}

Does this make sense? I can see that 0.0.0.0 is technically a valid IPv4 address, even if it makes no sense for the user to enter that. What about the other two? Why are they converted in the way they are and should I treat them as valid even if it might not be transparent for the user, who maybe just forgot to enter the periods (65536 instead of 6.5.5.36).

Any help is most appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

路还长,别太狂 2024-10-26 01:54:15

IPAddress.TryParse() 的作用不是检查字符串是否是有效的 IP 地址,而是检查字符串的内容是否可以解析(即;转换)为有效的 IP 地址。

事实上,测试用例中的所有选项都可以解析为表示 和 IP。归根结底是您的测试用例是有效的。问题在于您的测试用例的数据无效,或者您没有在测试用例中使用正确的工具来获得预期结果。

如果您专门测试有效的 IPv4,恰好有 4 个四边形(每个四边形都是 0 - 255 之间的整数),并且希望避免使用正则表达式,则可以改为拆分然后解析和验证。

public static bool IsIPv4(string value)
{
    var octets = value.Split('.');

    // if we do not have 4 octets, return false
    if (octets.Length!=4) return false;

    // for each octet
    foreach(var octet in octets) 
    {
        int q;
        // if parse fails 
        // or length of parsed int != length of octet string (i.e.; '1' vs '001')
        // or parsed int < 0
        // or parsed int > 255
        // return false
        if (!Int32.TryParse(octet, out q) 
            || !q.ToString().Length.Equals(octet.Length) 
            || q < 0 
            || q > 255) { return false; }

    }

    return true;
}

The job of IPAddress.TryParse() is not to check if the string is a valid IP address, but whether or not the content of the string can be parsed (i.e.; converted) to a valid IP address.

All of the options in your test cases can in fact be parsed to represent and IP. What it comes down to is that your test cases are valid. The issue is that the data for your test cases are not valid, or you're not using the right tool(s) in your test case to get the expected result.

If you're specifically testing for a valid IPv4, with exactly 4 quads (each being an integer between 0 - 255), and want to avoid regex your could instead split then parse and validate.

public static bool IsIPv4(string value)
{
    var octets = value.Split('.');

    // if we do not have 4 octets, return false
    if (octets.Length!=4) return false;

    // for each octet
    foreach(var octet in octets) 
    {
        int q;
        // if parse fails 
        // or length of parsed int != length of octet string (i.e.; '1' vs '001')
        // or parsed int < 0
        // or parsed int > 255
        // return false
        if (!Int32.TryParse(octet, out q) 
            || !q.ToString().Length.Equals(octet.Length) 
            || q < 0 
            || q > 255) { return false; }

    }

    return true;
}
爱已欠费 2024-10-26 01:54:15

它看起来像 IPAddress.Parse< 的文档/code>通过指出输入较少的部分可以方便地输入 A 类和 B 类地址来合理化此行为。我猜,如果您想强制使用由四部分组成的地址,您可能只想在将地址提供给 IPAddress.TryParse 之前检查地址中是否有三个句点。

一些代码供您参考:

// verify that IP consists of 4 parts
if (value.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries).Length == 4)
{
    IPAddress ipAddr;
    if (IPAddress.TryParse(value, out ipAddr))
    {
        // IP is valid
    }
    else
        // invalid IP
}
else
    // invalid IP

It looks like the docs for IPAddress.Parse rationalize this behavior by pointing out that entering fewer parts is convenient for entering class A and B addresses. If you want to force a four-part address, you might just want to check that there are three periods in the address before feeding it to IPAddress.TryParse, I guess.

Some code for your reference:

// verify that IP consists of 4 parts
if (value.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries).Length == 4)
{
    IPAddress ipAddr;
    if (IPAddress.TryParse(value, out ipAddr))
    {
        // IP is valid
    }
    else
        // invalid IP
}
else
    // invalid IP
葵雨 2024-10-26 01:54:15

如果您想对输入非常严格,那么您可以比较已解析的 IPAddressToString() 版本,如果不同则拒绝输入。

全零地址和其他类似的事情必须作为特殊情况来处理。

If you want to be very strict about your input, then you can compare the ToString() version of the parsed IPAddress, and reject the input if they are different.

The all-zero address, and other such things, would have to be handled as special cases.

明月松间行 2024-10-26 01:54:15

我建议:

    public bool IsValidIp(string addr)
    {
        IPAddress ip;
        bool valid = !string.IsNullOrEmpty(addr) && IPAddress.TryParse(addr, out ip);
        return valid;
    }

I suggest:

    public bool IsValidIp(string addr)
    {
        IPAddress ip;
        bool valid = !string.IsNullOrEmpty(addr) && IPAddress.TryParse(addr, out ip);
        return valid;
    }
倾城月光淡如水﹏ 2024-10-26 01:54:15
    public static bool IsIPv4(string ipAddress)
    {
        return Regex.IsMatch(ipAddress, @"^\d{1,3}(\.\d{1,3}){3}$") &&
            ipAddress.Split('.').SingleOrDefault(s => int.Parse(s) > 255) == null;
    }

其他答案要么允许 IPv6,要么允许输入“1.-0.1.1”。

    public static bool IsIPv4(string ipAddress)
    {
        return Regex.IsMatch(ipAddress, @"^\d{1,3}(\.\d{1,3}){3}$") &&
            ipAddress.Split('.').SingleOrDefault(s => int.Parse(s) > 255) == null;
    }

Other answers either allow IPv6 or allow input like "1.-0.1.1".

故事未完 2024-10-26 01:54:15

ipString 中的部分数量(每个部分由句点分隔)决定了 IP 地址的构造方式。一份地址直接存储在网络地址中。两部分地址为了方便指定 A 类地址,将前导部分放在网络地址的第一个字节中,将尾随部分放在网络地址的最右边的三个字节中。为了方便指定 B 类地址,三部分地址将第一部分放在第一个字节中,第二部分放在第二个字节中,最后部分放在网络地址最右边的两个字节中。例如:

零件数量和示例 ipString
IP 地址 1 的 IPv4 地址

--“65536”
0.0.255.255

2 -- “20.2”
20.0.0.2

2 --“20.65535”
20.0.255.255

3 --“128.1.2”
128.1.0.2

您可能需要参考MSDN文档
http://msdn.microsoft.com/en-us /library/system.net.ipaddress.parse.aspx

您最好的选择是 IPAddress.ToString() 或正则表达式。

The number of parts (each part is separated by a period) in ipString determines how the IP address is constructed. A one part address is stored directly in the network address. A two part address, convenient for specifying a class A address, puts the leading part in the first byte and the trailing part in the right-most three bytes of the network address. A three part address, convenient for specifying a class B address, puts the first part in the first byte, the second part in the second byte, and the final part in the right-most two bytes of the network address. For example:

Number of parts and example ipString
IPv4 address for IPAddress

1 -- "65536"
0.0.255.255

2 -- "20.2"
20.0.0.2

2 -- "20.65535"
20.0.255.255

3 -- "128.1.2"
128.1.0.2

You may want to refer MSDN documentation
http://msdn.microsoft.com/en-us/library/system.net.ipaddress.parse.aspx

Your best bet will be IPAddress.ToString() or regular expressions.

一刻暧昧 2024-10-26 01:54:15

是的,这些是有效地址。有关详细信息,请参阅 http://en.wikipedia.org/wiki/IPv4#Address_representations

Yes, those are valid addresses. See http://en.wikipedia.org/wiki/IPv4#Address_representations for more information.

烟花肆意 2024-10-26 01:54:15

虽然这个问题在两年前就得到了回答,但我认为提出我今天在寻找同样的东西时想到的内容是相关的,在找到这个页面后,我决定我太懒了,无法以编程方式完成所有验证。

如果通过 FormTextBox 接受信息,则使用 MaskedTextBox 更符合您的最佳利益。您可以强制用户以 IP 地址格式输入信息,而不必自己进行猜测。

用于此类验证的掩码是 990.990.990.990,其中表示 OptionalNumber、OptionalNumber、MandatoryNumber,因为 1.1.1.110.10。 10.10123.123.123.123 都是有效的 IP 地址格式。掩码与 Microsoft 在 Access 中使用的格式相同。

Although this question was answered like two years ago, I think it is relevant to bring up what I figured out when I was looking for the same thing today, and after finding this page decided I was far too lazy to go through all the validation progmatically.

If the information is being accepted through a Form and a TextBox, it would be in your best interest to use a MaskedTextBox instead. You can force the user to put in information in IP Address format instead of having to do the guesswork yourself.

The mask to be used for such validation is 990.990.990.990 which says OptionalNumber, OptionalNumber, MandatoryNumber because 1.1.1.1, 10.10.10.10, and 123.123.123.123 are all valid IP Address formats. The masks are the same format that Microsoft uses in Access.

┾廆蒐ゝ 2024-10-26 01:54:15

这是有道理的,因为 65536 等于 0x00010000 或 0.1.0.0。我猜 TryParse 也会接受十六进制数字。无论如何,我认为您不想接受普通用户的这样的值,但我认为这取决于最终用户。

It makes sense, as 65536 is equal to 0x00010000, or 0.1.0.0. I'm guessing TryParse will also accept hex numbers. In any case, I don't think that you'd want to accept such a value from a normal user, but I suppose that depends on the end user.

月光色 2024-10-26 01:54:15

下面的代码使用正则表达式,由 Roshe 建议

        string txt = textBox1.Text;

        string ValidIpAddressRegex = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9‌​]{2}|2[0-4][0-9]|25[0-5])$";    // IP validation 

        Regex r = new Regex(ValidIpAddressRegex, RegexOptions.IgnoreCase | RegexOptions.Singleline);
        Match m = r.Match(txt);

        if (!m.Success)
        {
          //Not a valid IP
        }

        else
        {


          //A valid IP

        }

The below code is using regex, suggested by Roshe

        string txt = textBox1.Text;

        string ValidIpAddressRegex = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9‌​]{2}|2[0-4][0-9]|25[0-5])$";    // IP validation 

        Regex r = new Regex(ValidIpAddressRegex, RegexOptions.IgnoreCase | RegexOptions.Singleline);
        Match m = r.Match(txt);

        if (!m.Success)
        {
          //Not a valid IP
        }

        else
        {


          //A valid IP

        }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文