Se connecter aux services web locaux à partir de simulateurs iOS et d’émulateurs Android

De nombreuses applications mobiles consomment des services web. Pendant la phase de développement, il est courant de déployer un service web localement et de le consommer à partir d’une application mobile en cours d’exécution dans le simulateur iOS ou l’émulateur Android. Cela évite d’avoir à déployer le service web sur un point de terminaison hébergé et garantit une expérience de débogage simple, car l’application mobile et le web service mobile sont exécutés localement.

Les applications mobiles en cours d’exécution dans le simulateur iOS ou l’émulateur Android peuvent consommer des services web ASP.NET Core exécutés localement et exposés via HTTP, comme suit :

  • Les applications en cours d’exécution dans le simulateur iOS peuvent se connecter aux services web HTTP locaux via l’adresse IP de vos machines ou le nom d’hôte localhost. Par exemple, si un service web HTTP local expose une opération GET via l’URI relatif /api/todoitems/, une application en cours d’exécution dans le simulateur iOS peut consommer l’opération en envoyant une requête GET à http://localhost:<port>/api/todoitems/.
  • Les applications en cours d’exécution dans l’émulateur Android peuvent se connecter aux services web HTTP locaux via l’adresse 10.0.2.2, qui représente un alias vers votre interface de bouclage hôte (127.0.0.1 sur votre ordinateur de développement). Par exemple, si un service web HTTP local expose une opération GET via l’URI relatif /api/todoitems/, une application en cours d’exécution dans l’émulateur Android peut consommer l’opération en envoyant une requête GET à http://10.0.2.2:<port>/api/todoitems/.

Toutefois, un travail supplémentaire est nécessaire pour qu’une application en cours d’exécution dans le simulateur iOS ou l’émulateur Android puisse consommer un service web local exposé via le protocole HTTPS. Pour ce scénario, le processus est le suivant :

  1. Créez un certificat de développement auto-signé sur votre ordinateur. Pour plus d’informations, consultez Créer un certificat de développement.
  2. Configurez votre projet pour utiliser la pile réseau appropriée HttpClient pour votre build de débogage. Pour plus d’informations, consultez Configurer votre projet.
  3. Spécifiez l’adresse de votre ordinateur local. Pour plus d’informations, consultez Spécifier l’adresse de l’ordinateur local.
  4. Contournez la vérification de sécurité du certificat de développement local. Pour plus d’informations, consultez Contourner la vérification de sécurité du certificat.

Chacun de ces points va être abordé à tour de rôle.

Créer un certificat de développement

L’installation du kit SDK .NET Core installe le certificat de développement ASP.NET Core HTTPS dans le magasin de certificats de l’utilisateur local. Mais même s’il a été installé, le certificat n’est pas approuvé. Pour approuver le certificat, effectuez cette étape unique afin d’exécuter l’outil dotnet dev-certs :

dotnet dev-certs https --trust

La commande suivante fournit de l’aide sur l’outil dev-certs :

dotnet dev-certs https --help

Sinon, lorsque vous exécutez un projet ASP.NET Core 2.1 (ou version ultérieure) qui utilise HTTPS, Visual Studio détecte si le certificat de développement est manquant et vous propose de l’installer et de l’approuver.

Remarque

Le certificat de développement HTTPS ASP.NET Core est auto-signé.

Pour plus d’informations sur l’activation du protocole HTTPS local sur votre ordinateur, consultez Activer HTTPS localement.

Configurer votre projet

Les applications Xamarin en cours d’exécution sur iOS et Android peuvent spécifier quelle pile réseau est utilisée par la classe HttpClient, les options étant une pile réseau gérée ou des piles réseau natives. La pile gérée fournit un haut niveau de compatibilité avec le code .NET existant, mais elle se limite à TLS 1.0, peut être plus lente et générer un fichier exécutable de plus grande taille. Les piles natives peuvent être plus rapides et garantir une meilleure sécurité, mais elles n’offrent pas toutes les fonctionnalités de la classe HttpClient.

iOS

Les applications Xamarin en cours d’exécution sur iOS peuvent utiliser la pile réseau gérée, ou les piles réseau natives CFNetwork ou NSUrlSession. Par défaut, les projets créés dans nouvelle plateforme iOS utilisent la pile réseau NSUrlSession (pour prendre en charge TLS 1.2) et des API natives pour améliorer les performances et générer un fichier exécutable de plus petite taille. Pour plus d’informations, consultez HttpClient et sélecteur d’implémentation de SSL/TLS pour iOS/macOS.

Android

Les applications Xamarin en cours d’exécution sur Android peuvent utiliser la pile réseau gérée HttpClient, ou la pile réseau native AndroidClientHandler. Par défaut, les projets créés dans nouvelle plateforme Android utilisent la pile réseau AndroidClientHandler (pour prendre en charge TLS 1.2) et des API natives pour améliorer les performances et générer un fichier exécutable de plus petite taille. Pour plus d’informations sur les piles réseau Android, consultez le sélecteur d’implémentation HTTPClient Stack et SSL/TLS pour Android.

Spécifier l’adresse de l’ordinateur local

Le simulateur iOS et l’émulateur Android fournissent un accès aux services web sécurisés en cours d’exécution sur votre ordinateur local. Mais ils utilisent chacun une adresse d’ordinateur local différente.

iOS

Le simulateur iOS utilise le réseau de l’ordinateur hôte. Les applications en cours d’exécution dans le simulateur peuvent ainsi se connecter aux services web exécutés sur votre ordinateur local via l’adresse IP de vos machines ou le nom d’hôte localhost. Par exemple, si un service web sécurisé local expose une opération GET via l’URI relatif /api/todoitems/, une application en cours d’exécution dans le simulateur iOS peut consommer l’opération en envoyant une requête GET à https://localhost:<port>/api/todoitems/.

Remarque

Lorsque vous exécutez une application mobile dans le simulateur iOS à partir de Windows, l’application s’affiche dans le simulateur iOS à distance pour Windows. Mais l’application est en cours d’exécution sur le Mac jumelé. Par conséquent, il n’existe aucun accès localhost à un service web en cours d’exécution dans Windows pour une application iOS en cours d’exécution sur un Mac.

Android

Chaque instance de l’émulateur Android est isolée des interfaces réseau de votre ordinateur de développement et s’exécute derrière un routeur virtuel. Un appareil émulé ne peut donc pas voir votre ordinateur de développement ou d’autres instances de l’émulateur sur le réseau.

Cependant, le routeur virtuel de chaque émulateur gère un espace de réseau spécial qui inclut des adresses préallouées, l’adresse 10.0.2.2 servant d’alias vers votre interface de bouclage hôte (127.0.0.1 sur votre ordinateur de développement). Par conséquent, si un service web sécurisé local expose une opération GET via l’URI relatif /api/todoitems/, une application en cours d’exécution dans le simulateur Android peut consommer l’opération en envoyant une requête GET à https://10.0.2.2:<port>/api/todoitems/.

Détecter le système d’exploitation

La classe DeviceInfo peut être utilisée pour détecter la plateforme sur laquelle l’application est en cours d’exécution. Le nom d’hôte approprié, qui permet d’accéder aux services web sécurisés locaux, peut être ainsi défini comme suit :

public static string BaseAddress =
    DeviceInfo.Platform == DevicePlatform.Android ? "https://10.0.2.2:5001" : "https://localhost:5001";
public static string TodoItemsUrl = $"{BaseAddress}/api/todoitems/";

Pour plus d’informations sur la classe, consultez Xamarin.Essentials : Informations sur l’appareilDeviceInfo.

Contourner la vérification de sécurité du certificat

Toute tentative pour appeler un service web sécurisé local à partir d’une application en cours d’exécution dans le simulateur iOS ou l’émulateur Android entraînera une exception HttpRequestException, même si vous utilisez la pile réseau gérée sur chaque plateforme. En effet, le certificat de développement HTTPS local est auto-signé, et les certificats auto-signés ne sont pas approuvés par iOS ou Android. Par conséquent, il est nécessaire d’ignorer les erreurs SSL lorsqu’une application consomme un service web sécurisé local. Pour ce faire, lorsque vous utilisez les piles réseau managées et natives sur iOS et Android, définissez la ServerCertificateCustomValidationCallback propriété sur un objet sur un HttpClientHandler rappel qui ignore le résultat de la vérification de sécurité de certificat pour le certificat de développement HTTPS local :

// This method must be in a class in a platform project, even if
// the HttpClient object is constructed in a shared project.
public HttpClientHandler GetInsecureHandler()
{
    HttpClientHandler handler = new HttpClientHandler();
    handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) =>
    {
        if (cert.Issuer.Equals("CN=localhost"))
            return true;
        return errors == System.Net.Security.SslPolicyErrors.None;
    };
    return handler;
}

Dans cet exemple de code, le résultat de la validation du certificat du serveur est retourné lorsque le certificat ayant fait l’objet de la validation n’est pas le certificat localhost. Pour obtenir ce certificat, le résultat de la validation est ignoré et la valeur true est renvoyée, indiquant que le certificat est valide. L’objet résultant HttpClientHandler doit être transmis en tant qu’argument au HttpClient constructeur pour les builds de débogage :

#if DEBUG
    HttpClientHandler insecureHandler = GetInsecureHandler();
    HttpClient client = new HttpClient(insecureHandler);
#else
    HttpClient client = new HttpClient();
#endif

Activer le trafic de texte clair HTTP

Si vous le souhaitez, vous pouvez configurer vos projets iOS et Android pour autoriser le trafic HTTP en texte clair. Si le service principal est configuré pour autoriser le trafic HTTP, vous pouvez spécifier HTTP dans les URL de base, puis configurer vos projets pour autoriser le trafic en texte clair :

public static string BaseAddress =
    DeviceInfo.Platform == DevicePlatform.Android ? "http://10.0.2.2:5000" : "http://localhost:5000";
public static string TodoItemsUrl = $"{BaseAddress}/api/todoitems/";

Désactivation d’iOS ATS

Pour activer le trafic local en texte clair sur iOS, vous devez désactiver ATS en ajoutant ce qui suit à votre fichier Info.plist :

<key>NSAppTransportSecurity</key>    
<dict>
    <key>NSAllowsLocalNetworking</key>
    <true/>
</dict>

Configuration de la sécurité réseau Android

Pour activer le trafic local en texte clair sur Android, vous devez créer une configuration de sécurité réseau en ajoutant un nouveau fichier XML nommé network_security_config.xml dans le dossier Resources/xml. Le fichier XML doit spécifier la configuration suivante :

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
  <domain-config cleartextTrafficPermitted="true">
    <domain includeSubdomains="true">10.0.2.2</domain>
  </domain-config>
</network-security-config>

Ensuite, configurez la propriété networkSecurityConfig sur le nœud d’application dans le manifeste Android :

<?xml version="1.0" encoding="utf-8"?>
<manifest>
    <application android:networkSecurityConfig="@xml/network_security_config">
        ...
    </application>
</manifest>

Vérifiez que l’action de génération est définie comme AndroidResource, sinon le fichier XML est introuvable au moment de la génération.