web-dev-qa-db-fra.com

Validation de l'adresse IP

Je refacture mon code et je voulais utiliser la méthode IPAddress.TryParse pour valider si une chaîne est une adresse IPv4 valide au lieu d'utiliser des expressions régulières:

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

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

    return false;
}

Mon test d'unité échoue maintenant car ces valeurs d'entrée renvoient true et sont analysées avec les objets IPAddress suivants:

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}

Est-ce que ça a du sens? Je peux voir que 0.0.0.0 est techniquement une adresse IPv4 valide, même si cela n’a aucun sens pour l’utilisateur de le saisir. Qu'en est-il des deux autres? Pourquoi sont-ils convertis tels quels et devrais-je les traiter comme valables même si cela peut ne pas être transparent pour l'utilisateur, qui a peut-être simplement oublié d'entrer les points (65536 au lieu de 6.5.5.36).

Toute aide est très appréciée.

13
Martin Buberl

Il semble que la documentation de IPAddress.Parse rationalise ce comportement en indiquant que la saisie de moins de parties est pratique pour la saisie d’adresses de classes A et B. Si vous voulez forcer une adresse en quatre parties, vous voudrez peut-être simplement vérifier qu'il y a trois points dans l'adresse avant de l'envoyer à IPAddress.TryParse, je suppose.

Un code pour votre référence:

// 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
9
mquander

Le travail de IPAddress.TryParse () ne consiste pas à vérifier si la chaîne est une adresse IP valide, mais si le contenu de la chaîne peut être analysé (c'est-à-dire converti) en une adresse IP valide. adresse. 

Toutes les options de vos cas de test peuvent en fait être analysées pour représenter et IP. En résumé, vos scénarios de test sont valides. Le problème est que les données de vos scénarios de test ne sont pas valides ou que vous n'utilisez pas les bons outils dans votre scénario de test pour obtenir le résultat attendu.

Si vous testez spécifiquement un IPv4 valide, avec exactement 4 quads (chacun étant un entier compris entre 0 et 255), et que vous souhaitez éviter les expressions rationnelles, vous pouvez au lieu de cela diviser puis analyser et valider.

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

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

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

        }

        return true;
    }
21
Mad Man Moon

Si vous voulez être très strict sur votre entrée, vous pouvez alors comparer la version ToString() de la IPAddress analysée et rejeter l'entrée si elles sont différentes.

L'adresse du zéro absolu, entre autres, devrait être traitée comme un cas spécial.

6
Jeffrey L Whitledge

Je suggère:

    public bool IsValidIp(string addr)
    {
        IPAddress ip;
        bool valid = !string.IsNullOrEmpty(addr) && IPAddress.TryParse(addr, out ip);
        return valid;
    }
5
user1756694
    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;
    }

D'autres réponses autorisent IPv6 ou permettent une entrée telle que "1.-0.1.1".

4
Dennis Gorelik

Le nombre de parties (chaque partie est séparée par un point) dans ipString détermine la manière dont l'adresse IP est construite. Une adresse en une partie est stockée directement dans l'adresse du réseau. Une adresse en deux parties, pratique pour spécifier une adresse de classe A, place la partie principale dans le premier octet et la partie suivante dans les trois octets les plus à droite de l'adresse réseau. Une adresse en trois parties, pratique pour spécifier une adresse de classe B, place la première partie dans le premier octet, la seconde partie dans le deuxième octet et la dernière dans les deux octets les plus à droite de l'adresse réseau. Par exemple:

Nombre de pièces et exemple ipString Adresse IPv4 pour 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

Vous souhaiterez peut-être consulter la documentation MSDN http://msdn.Microsoft.com/en-us/library/system.net.ipaddress.parse.aspx

Votre meilleur pari sera IPAddress.ToString () ou des expressions régulières. 

2
ukhardy

Bien que cette question ait reçu une réponse il y a deux ans environ, je pense qu'il est pertinent de revenir sur ce que j'ai découvert lorsque je cherchais la même chose aujourd'hui, et après avoir trouvé cette page, j'ai décidé que j'étais trop paresseux pour effectuer toutes les validations par étapes. .

Si les informations sont acceptées via Form et TextBox, il serait dans votre intérêt d’utiliser plutôt un MaskedTextBox. Vous pouvez forcer l'utilisateur à entrer des informations au format d'adresse IP au lieu de devoir vous-même tenter de deviner.

Le masque à utiliser pour cette validation est 990.990.990.990, qui indique OptionalNumber, OptionalNumber, MandatoryNumber car 1.1.1.1, 10.10.10.10 et 123.123.123.123 sont tous des formats d'adresse IP valides. Les masques sont au même format que Microsoft utilise dans Access.

1
Matt Miller

Oui, ce sont des adresses valides. Voir http://en.wikipedia.org/wiki/IPv4#Address_representations pour plus d'informations.

1
Jim Mischel

Cela a du sens, car 65536 est égal à 0x00010000, ou 0.1.0.0. J'imagine que TryParse acceptera également les nombres hexadécimaux. Dans tous les cas, je ne pense pas que vous souhaitiez accepter une telle valeur d'un utilisateur normal, mais je suppose que cela dépend de l'utilisateur final.

0
Jeff

Le code ci-dessous utilise regex, suggéré par 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

        }
0
dmn