Nawiązywanie połączenia z lokalnymi usługami internetowymi z symulatorów systemu iOS i emulatorów systemu Android
Wiele aplikacji mobilnych korzysta z usług internetowych. W fazie opracowywania często wdraża się lokalnie usługę internetową i korzysta z niej z aplikacji mobilnej działającej w symulatorze systemu iOS lub emulatorze systemu Android. Pozwala to uniknąć konieczności wdrażania usługi internetowej w hostowanym punkcie końcowym i umożliwia proste debugowanie, ponieważ zarówno aplikacja mobilna, jak i usługa internetowa działają lokalnie.
Aplikacje mobilne działające w symulatorze systemu iOS lub emulatorze systemu Android mogą korzystać z usług internetowych ASP.NET Core działających lokalnie i uwidocznionych za pośrednictwem protokołu HTTP w następujący sposób:
- Aplikacje działające w symulatorze systemu iOS mogą łączyć się z lokalnymi usługami internetowymi HTTP za pośrednictwem adresu IP maszyn lub za pośrednictwem
localhost
nazwy hosta. Na przykład, biorąc pod uwagę lokalną usługę internetową HTTP, 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 dohttp://localhost:<port>/api/todoitems/
. - Aplikacje działające w emulatorze systemu Android mogą łączyć się z lokalnymi usługami internetowymi HTTP za pośrednictwem
10.0.2.2
adresu, który jest aliasem interfejsu sprzężenia zwrotnego hosta (127.0.0.1
na maszynie dewelopera). Na przykład, biorąc pod uwagę lokalną usługę internetową HTTP, 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 dohttp://10.0.2.2:<port>/api/todoitems/
.
Jednak dodatkowa praca jest niezbędna, aby aplikacja uruchomiona w symulatorze systemu iOS lub emulatorze systemu Android mogła korzystać z lokalnej usługi internetowej uwidocznionej za pośrednictwem protokołu HTTPS. W tym scenariuszu proces jest następujący:
- Utwórz certyfikat programowania z podpisem własnym na maszynie. Aby uzyskać więcej informacji, zobacz Tworzenie certyfikatu programistycznego.
- Skonfiguruj projekt tak, aby używał odpowiedniego
HttpClient
stosu sieciowego dla kompilacji debugowania. Aby uzyskać więcej informacji, zobacz Konfigurowanie projektu. - Określ adres komputera lokalnego. Aby uzyskać więcej informacji, zobacz Określanie adresu komputera lokalnego.
- 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.
Tworzenie certyfikatu programistycznego
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.
Konfigurowanie projektu
Aplikacje platformy Xamarin działające w systemach iOS i Android mogą określać, który stos sieciowy jest używany przez HttpClient
klasę, z opcjami stosu zarządzanego sieci lub natywnymi stosami sieciowymi. Zarządzany stos zapewnia wysoki poziom zgodności z istniejącym kodem platformy .NET, ale jest ograniczony do protokołu TLS 1.0 i może być wolniejszy i powodować większy rozmiar pliku wykonywalnego. Natywne stosy mogą być szybsze i zapewniają lepsze zabezpieczenia, ale mogą nie zapewniać wszystkich funkcji HttpClient
klasy.
iOS
Aplikacje platformy Xamarin działające w systemie iOS mogą używać zarządzanego stosu sieciowego lub stosów natywnych CFNetwork
lub NSUrlSession
sieciowych. Domyślnie nowe projekty platformy systemu iOS używają stosu NSUrlSession
sieciowego do obsługi protokołu TLS 1.2 i używają natywnych interfejsów API w celu uzyskania lepszej wydajności i mniejszego rozmiaru pliku wykonywalnego. Aby uzyskać więcej informacji, zobacz Selektor implementacji protokołu HTTPClient i SSL/TLS dla systemu iOS/macOS.
Android
Aplikacje platformy Xamarin działające w systemie Android mogą używać zarządzanego HttpClient
stosu sieciowego lub natywnego AndroidClientHandler
stosu sieciowego. Domyślnie nowe projekty platformy Android używają stosu AndroidClientHandler
sieciowego, aby obsługiwać protokół TLS 1.2 i używać natywnych interfejsów API w celu uzyskania lepszej wydajności i mniejszego rozmiaru pliku wykonywalnego. Aby uzyskać więcej informacji na temat stosów sieciowych systemu Android, zobacz HttpClient Stack and SSL/TLS Implementation selector for Android (Selektor implementacji protokołu SSL/TLS dla systemu Android).
Określanie adresu komputera lokalnego
Symulator systemu iOS i emulator systemu Android zapewniają dostęp do bezpiecznych usług internetowych uruchomionych na komputerze lokalnym. Jednak adres komputera lokalnego jest inny dla każdego.
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 za pośrednictwem localhost
nazwy hosta. Na przykład, biorąc pod uwagę lokalną bezpieczną 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 https://localhost:<port>/api/todoitems/
.
Uwaga
W przypadku uruchamiania aplikacji mobilnej 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.
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ą bezpieczną 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 https://10.0.2.2:<port>/api/todoitems/
.
Wykrywanie systemu operacyjnego
Klasa DeviceInfo
może służyć do wykrywania platformy, na którym działa aplikacja. Odpowiednią nazwę hosta, która umożliwia dostęp do lokalnych bezpiecznych usług internetowych, można 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 DeviceInfo
klasy, zobacz Xamarin.Essentials: Device Information (Xamarin.Essentials: informacje o urządzeniu).
Pomijanie sprawdzania zabezpieczeń certyfikatu
Próba wywołania lokalnej bezpiecznej usługi internetowej z poziomu aplikacji uruchomionej w symulatorze systemu iOS lub emulatorze systemu Android spowoduje HttpRequestException
zgłoszenie nawet w przypadku korzystania z zarządzanego stosu sieciowego na każdej platformie. Dzieje się tak, ponieważ lokalny certyfikat dewelopera HTTPS jest z podpisem własnym, a certyfikaty z podpisem własnym nie są zaufane przez system iOS lub Android. W związku z tym należy zignorować błędy SSL, gdy aplikacja korzysta z lokalnej bezpiecznej usługi internetowej. Można to zrobić w przypadku używania zarówno zarządzanych, jak i natywnych stosów sieciowych w systemach iOS i Android, ustawiając ServerCertificateCustomValidationCallback
właściwość obiektu na HttpClientHandler
wywołanie zwrotne, które ignoruje wynik sprawdzania zabezpieczeń certyfikatu dla lokalnego certyfikatu dewelopera HTTPS:
// 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;
}
W tym przykładzie kodu wynik weryfikacji certyfikatu serwera jest zwracany, gdy certyfikat, który przeszedł walidację, nie jest certyfikatem localhost
. W przypadku tego certyfikatu wynik weryfikacji jest ignorowany i true
zwracany, wskazując, że certyfikat jest prawidłowy. Wynikowy HttpClientHandler
obiekt powinien zostać przekazany jako argument do konstruktora HttpClient
dla kompilacji debugowania:
#if DEBUG
HttpClientHandler insecureHandler = GetInsecureHandler();
HttpClient client = new HttpClient(insecureHandler);
#else
HttpClient client = new HttpClient();
#endif
Włączanie ruchu w postaci zwykłego tekstu HTTP
Opcjonalnie możesz skonfigurować projekty dla systemów iOS i Android, aby zezwalać na ruch HTTP w postaci zwykłego tekstu. Jeśli usługa zaplecza jest skonfigurowana tak, aby zezwalała na ruch HTTP, możesz określić protokół HTTP w podstawowych adresach URL, a następnie skonfigurować projekty tak, aby zezwalały na ruch w postaci zwykłego tekstu:
public static string BaseAddress =
DeviceInfo.Platform == DevicePlatform.Android ? "http://10.0.2.2:5000" : "http://localhost:5000";
public static string TodoItemsUrl = $"{BaseAddress}/api/todoitems/";
Rezygnacja z usługi ATS w systemie iOS
Aby włączyć ruch lokalny w postaci zwykłego tekstu w systemie iOS, należy zrezygnować z usługi ATS , dodając następujące informacje do pliku Info.plist :
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsLocalNetworking</key>
<true/>
</dict>
Konfiguracja zabezpieczeń sieci systemu Android
Aby włączyć ruch lokalny w postaci zwykłego tekstu w systemie Android, należy utworzyć konfigurację zabezpieczeń sieci, dodając nowy plik XML o nazwie network_security_config.xml w folderze Resources/xml . 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>
Następnie skonfiguruj właściwość networkSecurityConfig w węźle aplikacji w manifeście systemu Android:
<?xml version="1.0" encoding="utf-8"?>
<manifest>
<application android:networkSecurityConfig="@xml/network_security_config">
...
</application>
</manifest>
Upewnij się, że akcja kompilacji jest ustawiona jako AndroidResource. W przeciwnym razie plik XML nie zostanie znaleziony w czasie kompilacji.