Udostępnij za pośrednictwem


Nawiązywanie połączenia z lokalnymi usługami internetowymi z emulatorów systemu Android i symulatorów systemu iOS

Przeglądaj przykład. Przeglądanie przykładu

Wiele aplikacji mobilnych i klasycznych korzysta z usług internetowych. W fazie opracowywania oprogramowania często wdraża się lokalnie usługę internetową i korzysta z niej z aplikacji działającej w emulatorze systemu Android lub symulatorze systemu iOS. Pozwala to uniknąć konieczności wdrażania usługi internetowej w hostowanym punkcie końcowym i umożliwia proste środowisko debugowania, ponieważ zarówno aplikacja, jak i usługa internetowa działają lokalnie.

Wieloplatformowe aplikacje interfejsu użytkownika aplikacji platformy .NET (.NET MAUI), które działają w systemie Windows lub MacCatalyst, mogą korzystać z usług internetowych platformy ASP.NET Core działających lokalnie za pośrednictwem protokołu HTTP lub HTTPS bez konieczności wykonywania żadnych dodatkowych czynności, pod warunkiem, że masz zaufany certyfikat programowania. Jednak dodatkowa praca jest wymagana, gdy aplikacja jest uruchomiona w emulatorze systemu Android lub symulatorze systemu iOS, a proces różni się w zależności od tego, czy usługa internetowa jest uruchomiona za pośrednictwem protokołu HTTP, czy HTTPS.

Adres komputera lokalnego

Emulator systemu Android i symulator systemu iOS zapewniają dostęp do usług internetowych działających za pośrednictwem protokołu HTTP lub HTTPS na komputerze lokalnym. Jednak adres komputera lokalnego jest inny dla każdego.

Android

Każde wystąpienie emulatora systemu Android jest odizolowane od interfejsów sieciowych maszyny deweloperów i działa za routerem wirtualnym. W związku z tym emulowane urządzenie nie może zobaczyć maszyny dewelopera ani innych wystąpień emulatora w sieci.

Jednak router wirtualny dla każdego emulatora zarządza specjalną przestrzenią sieciową zawierającą wstępnie przydzielone adresy, a 10.0.2.2 adres jest aliasem interfejsu sprzężenia zwrotnego hosta (127.0.0.1 na maszynie dewelopera). W związku z tym, biorąc pod uwagę lokalną usługę internetową, która uwidacznia operację GET za pośrednictwem /api/todoitems/ względnego identyfikatora URI, aplikacja uruchomiona w emulatorze systemu Android może korzystać z operacji, wysyłając żądanie GET do http://10.0.2.2:<port>/api/todoitems/ lub https://10.0.2.2:<port>/api/todoitems/.

iOS

Symulator systemu iOS używa sieci maszyny hosta. W związku z tym aplikacje uruchomione w symulatorze mogą łączyć się z usługami internetowymi uruchomionymi na komputerze lokalnym za pośrednictwem adresu IP maszyn lub nazwy localhost hosta. Na przykład, biorąc pod uwagę lokalną usługę internetową, która uwidacznia operację GET za pośrednictwem /api/todoitems/ względnego identyfikatora URI, aplikacja uruchomiona w symulatorze systemu iOS może korzystać z operacji, wysyłając żądanie GET do http://localhost:<port>/api/todoitems/ lub https://localhost:<port>/api/todoitems/.

Uwaga

W przypadku uruchamiania aplikacji MAUI platformy .NET w symulatorze systemu iOS z systemu Windows aplikacja jest wyświetlana w zdalnym symulatorze systemu iOS dla systemu Windows. Jednak aplikacja jest uruchomiona na sparowanym komputerze Mac. W związku z tym nie ma dostępu localhost do usługi internetowej uruchomionej w systemie Windows dla aplikacji systemu iOS uruchomionej na komputerze Mac.

Lokalne usługi internetowe uruchomione za pośrednictwem protokołu HTTP

Aplikacja MAUI platformy .NET uruchomiona w emulatorze systemu Android lub symulatorze systemu iOS może korzystać z usługi internetowej platformy ASP.NET Core uruchomionej lokalnie za pośrednictwem protokołu HTTP. Można to osiągnąć, konfigurując projekt aplikacji .NET MAUI i projekt usługi internetowej ASP.NET Core, aby umożliwić ruch HTTP w postaci zwykłego tekstu.

W kodzie, który definiuje adres URL lokalnej usługi internetowej w aplikacji .NET MAUI, upewnij się, że adres URL usługi internetowej określa schemat HTTP i poprawną nazwę hosta. Klasa DeviceInfo może służyć do wykrywania platformy, na którym działa aplikacja. Poprawną nazwę hosta można następnie ustawić w następujący sposób:

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

Aby uzyskać więcej informacji na temat klasy, zobacz Informacje o urządzeniuDeviceInfo.

Ponadto, aby uruchomić aplikację w systemie Android, musisz dodać wymaganą konfigurację sieci i uruchomić aplikację w systemie iOS, musisz zrezygnować z usługi Apple Transport Security (ATS). Aby uzyskać więcej informacji, zobacz Konfiguracja sieci systemu Android i konfiguracja usługi ATS systemu iOS.

Należy również upewnić się, że usługa internetowa ASP.NET Core jest skonfigurowana tak, aby zezwalała na ruch HTTP. Można to osiągnąć, dodając profil HTTP do profiles sekcji launchSettings.json w projekcie usługi internetowej ASP.NET Core:

{
  ...
  "profiles": {
    "http": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": true,
      "launchUrl": "api/todoitems",
      "applicationUrl": "http://localhost:5000",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    ...
  }
}

Aplikacja MAUI platformy .NET uruchomiona w emulatorze systemu Android lub symulatorze systemu iOS może następnie korzystać z usługi internetowej ASP.NET Core działającej lokalnie za pośrednictwem protokołu HTTP, pod warunkiem, że usługa internetowa jest uruchamiana z profilem http .

Konfiguracja sieci systemu Android

Istnieją dwa główne podejścia do włączania ruchu lokalnego w postaci zwykłego tekstu w systemie Android:

Włączanie ruchu sieciowego w postaci zwykłego tekstu dla wszystkich domen

Ruch sieciowy w postaci zwykłego tekstu dla wszystkich domen można włączyć, ustawiając UsesCleartextTraffic właściwość atrybutu Application na true. Należy to zrobić w pliku Platformy > android > MainApplication.cs w projekcie aplikacji .NET MAUI i powinny być opakowane w element , #if DEBUG aby upewnić się, że nie jest on przypadkowo włączony w aplikacji produkcyjnej:

#if DEBUG
[Application(UsesCleartextTraffic = true)]
#else
[Application]
#endif
public class MainApplication : MauiApplication
{
    public MainApplication(IntPtr handle, JniHandleOwnership ownership)
        : base(handle, ownership)
    {
    }

    protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
}

Uwaga

Właściwość UsesCleartextTraffic jest ignorowana w systemie Android 7.0 (API 24) i nowszym, jeśli istnieje plik konfiguracji zabezpieczeń sieci.

Włączanie ruchu sieciowego w postaci zwykłego tekstu dla domeny localhost

Ruch sieciowy w postaci zwykłego localhost tekstu dla domeny można włączyć, tworząc plik konfiguracji zabezpieczeń sieci. Można to osiągnąć, dodając nowy plik XML o nazwie network_security_config.xml do folderu Platforms\Android\Resources\xml w projekcie aplikacji .NET MAUI. Plik XML powinien określać następującą konfigurację:

<?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>

Uwaga

Upewnij się, że akcja kompilacji pliku network_security_config.xml jest ustawiona na Wartość AndroidResource.

Następnie skonfiguruj właściwość networkSecurityConfig w węźle aplikacji w pliku Platforms\Android\AndroidManifest.xml w projekcie aplikacji .NET MAUI:

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

Aby uzyskać więcej informacji na temat plików konfiguracji zabezpieczeń sieci, zobacz Konfiguracja zabezpieczeń sieci w developer.android.com.

Konfiguracja usługi ATS systemu iOS

Aby włączyć ruch lokalny w postaci zwykłego tekstu w systemie iOS, należy zrezygnować z usługi Apple Transport Security (ATS) w aplikacji .NET MAUI. Można to osiągnąć, dodając następującą konfigurację do pliku Platformy\iOS\Info.plist w projekcie aplikacji .NET MAUI:

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

Aby uzyskać więcej informacji na temat usługi ATS, zobacz Zapobieganie niezabezpieczonym połączeniom sieciowym w developer.apple.com.

Lokalne usługi internetowe uruchomione za pośrednictwem protokołu HTTPS

Aplikacja MAUI platformy .NET uruchomiona w emulatorze systemu Android lub symulatorze systemu iOS może korzystać z usługi internetowej platformy ASP.NET Core uruchomionej lokalnie za pośrednictwem protokołu HTTPS. Proces włączania tego procesu jest następujący:

  1. Ufaj certyfikatowi programistycznemu z podpisem własnym na maszynie. Aby uzyskać więcej informacji, zobacz Ufanie certyfikatowi programistycznemu.
  2. Określ adres komputera lokalnego. Aby uzyskać więcej informacji, zobacz Określanie adresu komputera lokalnego.
  3. Pomiń sprawdzanie zabezpieczeń certyfikatu programowania lokalnego. Aby uzyskać więcej informacji, zobacz Obejście sprawdzania zabezpieczeń certyfikatu.

Każdy element zostanie omówiony z kolei.

Ufaj certyfikatowi programistycznemu

Zainstalowanie zestawu .NET Core SDK powoduje zainstalowanie certyfikatu dewelopera ASP.NET Core HTTPS w magazynie certyfikatów użytkownika lokalnego. Jednak po zainstalowaniu certyfikatu nie jest zaufany. Aby ufać certyfikatowi, wykonaj następujący jednorazowy krok, aby uruchomić narzędzie dotnet dev-certs :

dotnet dev-certs https --trust

Następujące polecenie zapewnia pomoc w narzędziu dev-certs :

dotnet dev-certs https --help

Alternatywnie po uruchomieniu projektu ASP.NET Core 2.1 (lub nowszego), który używa protokołu HTTPS, program Visual Studio wykryje, czy brakuje certyfikatu deweloperskiego i zaoferuje jego zainstalowanie i zaufanie.

Uwaga

Certyfikat dewelopera ASP.NET Core HTTPS jest z podpisem własnym.

Aby uzyskać więcej informacji na temat włączania lokalnego protokołu HTTPS na maszynie, zobacz Włączanie lokalnego protokołu HTTPS.

Określanie adresu komputera lokalnego

W kodzie, który definiuje adres URL lokalnej usługi internetowej w aplikacji .NET MAUI, upewnij się, że adres URL usługi internetowej określa schemat HTTPS i poprawną nazwę hosta. Klasa DeviceInfo może służyć do wykrywania platformy, na którym działa aplikacja. Poprawną nazwę hosta można następnie ustawić w następujący sposób:

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

Aby uzyskać więcej informacji na temat klasy, zobacz Informacje o urządzeniuDeviceInfo.

Pomijanie sprawdzania zabezpieczeń certyfikatu

Próba wywołania lokalnej bezpiecznej usługi internetowej z aplikacji MAUI platformy .NET uruchomionej w emulatorze systemu Android spowoduje java.security.cert.CertPathValidatorException zgłoszenie komunikatu wskazującego, że kotwica zaufania dla ścieżki certyfikacji nie została znaleziona. Podobnie próba wywołania lokalnej bezpiecznej usługi internetowej z poziomu aplikacji MAUI platformy .NET uruchomionej w symulatorze systemu iOS spowoduje NSURLErrorDomain wystąpienie błędu z komunikatem wskazującym, że certyfikat serwera jest nieprawidłowy. Te błędy występują, ponieważ lokalny certyfikat dewelopera HTTPS jest z podpisem własnym, a certyfikaty z podpisem własnym nie są zaufane przez system Android lub iOS. W związku z tym należy zignorować błędy PROTOKOŁU SSL, gdy aplikacja korzysta z lokalnej bezpiecznej usługi internetowej.

Można to osiągnąć, przekazując skonfigurowane wersje klas natywnych HttpMessageHandler do HttpClient konstruktora, co instruuje klasę HttpClient , aby ufała komunikacji localhost za pośrednictwem protokołu HTTPS. Klasa HttpMessageHandler jest abstrakcyjną klasą, której implementacja w systemie Android jest dostarczana przez AndroidMessageHandler klasę i której implementacja w systemie iOS jest dostarczana przez klasę NSUrlSessionHandler .

W poniższym przykładzie przedstawiono klasę, która konfiguruje AndroidMessageHandler klasę w systemie Android i NSUrlSessionHandler klasę w systemie iOS w celu zaufania komunikacji localhost za pośrednictwem protokołu HTTPS:

public class HttpsClientHandlerService
{
    public HttpMessageHandler GetPlatformMessageHandler()
    {
#if ANDROID
        var handler = new Xamarin.Android.Net.AndroidMessageHandler();
        handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) =>
        {
            if (cert != null && cert.Issuer.Equals("CN=localhost"))
                return true;
            return errors == System.Net.Security.SslPolicyErrors.None;
        };
        return handler;
#elif IOS
        var handler = new NSUrlSessionHandler
        {
            TrustOverrideForUrl = IsHttpsLocalhost
        };
        return handler;
#else
     throw new PlatformNotSupportedException("Only Android and iOS supported.");
#endif
    }

#if IOS
    public bool IsHttpsLocalhost(NSUrlSessionHandler sender, string url, Security.SecTrust trust)
    {
        return url.StartsWith("https://localhost");
    }
#endif
}

W systemie Android GetPlatformMessageHandler metoda zwraca AndroidMessageHandler obiekt. Metoda GetPlatformMessageHandler ustawia ServerCertificateCustomValidationCallback właściwość obiektu na AndroidMessageHandler wywołanie zwrotne, które ignoruje wynik sprawdzania zabezpieczeń certyfikatu dla lokalnego certyfikatu programowania HTTPS.

W systemie iOS GetPlatformMessageHandler metoda zwraca NSUrlSessionHandler obiekt, który ustawia jego TrustOverrideForUrl właściwość na delegata o nazwie IsHttpsLocalHost zgodnej z podpisem delegata NSUrlSessionHandler.NSUrlSessionHandlerTrustOverrideForUrlCallback . Delegat IsHttpsLocalHost zwraca wartość true , gdy adres URL zaczyna się od https://localhost.

Wynikowy HttpClientHandler obiekt można następnie przekazać jako argument do konstruktora HttpClient dla kompilacji debugowania:

#if DEBUG
            HttpsClientHandlerService handler = new HttpsClientHandlerService();
            HttpClient client = new HttpClient(handler.GetPlatformMessageHandler());
#else
            client = new HttpClient();
#endif

Aplikacja MAUI platformy .NET uruchomiona w emulatorze systemu Android lub symulatorze systemu iOS może następnie korzystać z usługi internetowej ASP.NET Core działającej lokalnie za pośrednictwem protokołu HTTPS.