Подключение локальным веб-службам из эмуляторов Android и симуляторов iOS

Browse sample. Обзор примера

Многие мобильные и классические приложения используют веб-службы. На этапе разработки программного обеспечения обычно развертывается веб-служба локально и используется из приложения, работающего в эмуляторе Android или симуляторе iOS. Это позволяет избежать необходимости развертывать веб-службу в размещенной конечной точке и выполнять простую отладку, так как приложение и веб-служба выполняются локально.

Приложения многоплатформенного пользовательского интерфейса приложений .NET (.NET MAUI), работающие в Windows или MacCatalyst, могут использовать веб-службы ASP.NET Core, работающие локально по протоколу HTTP или HTTPS без дополнительной работы, если вы доверяли сертификату разработки. Однако при работе приложения в эмуляторе Android или симуляторе iOS требуется дополнительная работа, а процесс отличается в зависимости от того, работает ли веб-служба по протоколу HTTP или HTTPS.

Адрес локального компьютера

Эмулятор Android и симулятор iOS предоставляют доступ к веб-службам, работающим через HTTP или HTTPS на локальном компьютере. Но адреса локального компьютера при этом будут разными.

Android

Каждый экземпляр Android Emulator изолирован от сетевых интерфейсов компьютера разработки с помощью виртуального маршрутизатора. Таким образом, эмулируемое устройство не может видеть компьютер разработки или другие экземпляры эмулятора в сети.

Виртуальный маршрутизатор каждого эмулятора управляет специализированным сетевым пространством, которое имеет предварительно выделенные адреса, а адрес 10.0.2.2 является псевдонимом для интерфейса замыкания узла на себя (127.0.0.1 на компьютере разработки). Таким образом, учитывая локальную веб-службу, которая предоставляет операцию GET через /api/todoitems/ относительный универсальный код ресурса (URI), приложение, работающее в эмуляторе Android, может использовать операцию, отправив запрос GET или http://10.0.2.2:<port>/api/todoitems/https://10.0.2.2:<port>/api/todoitems/.

iOS

iOS Simulator использует сеть главного компьютера. Таким образом, приложения, работающие в симуляторе, могут подключаться к веб-службам, работающим на локальном компьютере, через IP-адрес компьютеров или через localhost имя узла. Например, учитывая локальную веб-службу, которая предоставляет операцию GET через /api/todoitems/ относительный универсальный код ресурса (URI), приложение, работающее на симуляторе iOS, может использовать операцию, отправив запрос GET или http://localhost:<port>/api/todoitems/https://localhost:<port>/api/todoitems/.

Примечание.

При запуске приложения .NET MAUI в симуляторе iOS из Windows приложение отображается в удаленном симуляторе iOS для Windows. Однако приложение работает на парном Компьютере Mac. Поэтому нет доступа localhost к веб-службе, работающей в Windows для приложения iOS, работающего на Компьютере Mac.

Локальные веб-службы, работающие по протоколу HTTP

Приложение .NET MAUI, работающее в эмуляторе Android или симуляторе iOS, может использовать веб-службу ASP.NET Core, которая работает локально по протоколу HTTP. Это можно сделать, настроив проект приложения .NET MAUI и проект веб-службы ASP.NET Core, чтобы разрешить чистый текстовый трафик HTTP.

В коде, который определяет URL-адрес локальной веб-службы в приложении .NET MAUI, убедитесь, что URL-адрес веб-службы указывает схему HTTP и правильное имя узла. Класс DeviceInfo можно использовать для обнаружения платформы, в которую запущено приложение. Затем можно задать правильное имя узла следующим образом:

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

Дополнительные сведения о классе см. в разделе "Сведения об DeviceInfo устройстве".

Кроме того, чтобы запустить приложение на Android, необходимо добавить необходимую конфигурацию безопасности сети и запустить приложение в iOS, необходимо отказаться от защиты транспорта Apple (ATS). Дополнительные сведения см. в разделе "Конфигурация безопасности сети Android" и конфигурация iOS ATS.

Кроме того, необходимо убедиться, что веб-служба ASP.NET Core настроена для разрешения HTTP-трафика. Это можно сделать, добавив профиль HTTP в profiles раздел запуска Параметры.json в проекте веб-службы ASP.NET Core:

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

Приложение .NET MAUI, работающее в эмуляторе Android или симуляторе iOS, затем может использовать веб-службу ASP.NET Core, которая работает локально по протоколу HTTP, если веб-служба запускается с http профилем.

Конфигурация сетевой безопасности в Android

Чтобы включить локальный трафик с четким текстом в Android, необходимо создать файл конфигурации безопасности сети. Это можно сделать, добавив новый XML-файл с именем network_security_config.xml в папку Platform\Android\Resources\xml в проекте приложения .NET MAUI. XML-файл должен содержать следующую конфигурацию:

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

Примечание.

Убедитесь, что для действия сборки файла network_security_config.xml задано значение AndroidResource.

Затем настройте свойство networkSecurityConfig на узле приложения в файле Platform\Android\AndroidManifest.xml в проекте приложения .NET MAUI:

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

Дополнительные сведения о файлах конфигурации безопасности сети см. в разделе "Конфигурация безопасности сети" в developer.android.com.

Конфигурация iOS ATS

Чтобы включить локальный трафик с четким текстом в iOS, вы должны отказаться от защиты транспорта Apple (ATS) в приложении .NET MAUI. Это можно сделать, добавив следующую конфигурацию в файл Platform\iOS\Info.plist в проекте приложения .NET MAUI:

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

Дополнительные сведения об ATS см. в разделе "Предотвращение небезопасных Подключение сетей" на developer.apple.com.

Локальные веб-службы, работающие по протоколу HTTPS

Приложение .NET MAUI, работающее в эмуляторе Android или симуляторе iOS, может использовать веб-службу ASP.NET Core, которая работает локально по протоколу HTTPS. Этот процесс включается следующим образом:

  1. Доверяйте самозаверяющий сертификат разработки на компьютере. Дополнительные сведения см. в разделе "Доверять сертификату разработки".
  2. Укажите адрес своего локального компьютера. Дополнительные сведения см. в разделе Указание адреса локального компьютера.
  3. Выполните обход проверки безопасности сертификата разработки. Дополнительные сведения см. в разделе Обход проверки безопасности сертификата.

Далее последовательно рассматриваются все эти этапы.

Доверять сертификату разработки

Установка пакета SDK для .NET Core устанавливает сертификат разработки ASP.NET Core HTTPS в хранилище сертификатов локального пользователя. Но устанавливаемый сертификат не является доверенным. Чтобы сделать его доверенным, выполните следующее однократное действие для запуска средства .NET dev-certs.

dotnet dev-certs https --trust

Следующая команда вызывает справку по средству dev-certs.

dotnet dev-certs https --help

Кроме того, при запуске проекта ASP.NET Core 2.1 (или следующих версий), использующего протокол HTTPS, Visual Studio проверяет наличие сертификата разработки и предлагает установить его и сделать доверенным.

Примечание.

Сертификат разработки HTTPS ASP.NET Core является самозаверяющим.

Дополнительные сведения о включении протокола HTTPS в локальной среде на компьютере см. в разделе Включение локального HTTPS.

Указание адреса локального компьютера

В коде, определяющем URL-адрес локальной веб-службы в приложении .NET MAUI, убедитесь, что URL-адрес веб-службы указывает схему HTTPS и правильное имя узла. Класс DeviceInfo можно использовать для обнаружения платформы, в которую запущено приложение. Затем можно задать правильное имя узла следующим образом:

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

Дополнительные сведения о классе см. в разделе "Сведения об DeviceInfo устройстве".

Обход проверки безопасности сертификата

При попытке вызвать локальную безопасную веб-службу из приложения .NET MAUI, работающего в эмуляторе Android, возникает java.security.cert.CertPathValidatorException сообщение, указывающее, что привязка доверия для пути сертификации не найдена. Аналогичным образом попытка вызова локальной безопасной веб-службы из приложения .NET MAUI, работающего в симуляторе iOS, приведет к NSURLErrorDomain ошибке с сообщением о том, что сертификат сервера недопустим. Эти ошибки возникают из-за того, что локальный сертификат разработки HTTPS является самозаверяемым, а самозаверяющий сертификат не доверяется Android или iOS. Поэтому необходимо игнорировать ошибки SSL, когда приложение использует локальную безопасную веб-службу.

Это можно сделать, передав настроенные версии собственных HttpMessageHandler классов HttpClient конструктору, которые указывают HttpClient классу доверять локальному обмену данными через HTTPS. Класс HttpMessageHandler является абстрактным классом, реализация которого в Android предоставляется AndroidMessageHandler классом, и реализация которого в iOS предоставляется классом NSUrlSessionHandler .

В следующем примере показан класс, который настраивает AndroidMessageHandler класс в Android и NSUrlSessionHandler класс в iOS для доверия к локальному обмену данными через 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)
    {
        if (url.StartsWith("https://localhost"))
            return true;
        return false;
    }
#endif
}

В Android GetPlatformMessageHandler метод возвращает AndroidMessageHandler объект. Метод GetPlatformMessageHandler задает ServerCertificateCustomValidationCallback свойство объекта AndroidMessageHandler обратному вызову, который игнорирует результат безопасности сертификата проверка для локального сертификата разработки HTTPS.

В iOS GetPlatformMessageHandler метод возвращает объект, который задает NSUrlSessionHandler его TrustOverrideForUrl свойство делегату с именем IsHttpsLocalHost делегата, который соответствует сигнатуре делегата NSUrlSessionHandler.NSUrlSessionHandlerTrustOverrideForUrlCallback . Делегат IsHttpsLocalHost возвращается true при запуске https://localhostURL-адреса.

Затем результирующий HttpClientHandler объект можно передать в качестве аргумента конструктору HttpClient для отладочных сборок:

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

Затем приложение .NET MAUI, работающее в эмуляторе Android или симуляторе iOS, может использовать веб-службу ASP.NET Core, которая работает локально по протоколу HTTPS.