Aplikacja Expo nie łączy się przez HTTP na Androidzie 9: to cleartext, nie VPN
Build Expo wywołujący zwykłe HTTP API zawodzi na Androidzie 9 i nowszym. Tunel jest niewinny: flaga cleartext należy do konfiguracji builda.
Wydaliście nowy build, przeszliście na VPN, a ten sam ekran przestał się ładować. Na Androidzie 9 i nowszym częstsze wyjaśnienie jest nudniejsze: platforma odmawia zwykłego HTTP aplikacjom kierującym się na API 28 lub wyższe, a VPN zmienił tylko tyle kontekstu, by to ujawnić. Błąd, który widzisz, zależy od klienta HTTP, dlatego tak rzadko mówi cleartext.
Czym ten błąd właściwie jest
Od Androida 9 platforma domyślnie blokuje cleartext, gdy tylko aplikacja kieruje się na poziom API 28 lub wyższy. Żądanie do zwykłego adresu HTTP jest odrzucane przez platformę, zanim urządzenie opuści choćby jeden pakiet. To, jaki błąd zobaczysz, zależy od biblioteki HTTP: czasem ogólny błąd sieci, czasem przekroczenie limitu czasu, czasem komunikat, który wprost nazywa cleartext. Czego nigdy nie robi, to dotarcie do twojego serwera. Android dokumentuje domyślne zachowanie i alternatywę ograniczoną do domen w przewodniku po konfiguracji zabezpieczeń.
Przeglądarka na tym samym urządzeniu nadal potrafi wczytać stronę, i to jest wskazówka, którą większość ludzi przeoczy. Przeglądarki nie podlegają polityce bezpieczeństwa sieci twojej aplikacji.
Dlaczego obwinia się VPN
Zwykle zmieniają się trzy rzeczy naraz. Aplikacja może rozwiązywać inną nazwę hosta po połączeniu VPN, urządzenie może być nowe z nowszym buildem, albo sam build mógł przejść na docelowy poziom API, który uruchamia domyślne zachowanie. VPN jest widoczny, a docelowy SDK nie, więc to VPN dostaje zgłoszenie.
Porównaj poziomy docelowe starego i nowego builda, zanim dotkniesz konfiguracji sieci. Aplikacja kierująca się na 27 lub niżej jest zwolniona, co wyjaśnia każdy raport w stylu «u mnie działa na starym telefonie».
Gdzie faktycznie trafia flaga Expo
W zarządzanym projekcie Expo dodanie ustawienia do app.json nie edytuje manifestu Androida, ponieważ manifest tworzą prebuild i buildy deweloperskie. To plugin konfiguracji zapisuje ustawienie na tym etapie. Wspierana droga to expo-build-properties, skonfigurowany w konfiguracji aplikacji z opcją cleartext pod android.
{
"plugins": [
["expo-build-properties", {
"android": { "usesCleartextTraffic": true }
}]
]
}Fragment ustawia tylko opcję pluginu; manifest powstaje później. Uruchom prebuild albo świeży build klienta deweloperskiego, a następnie przed ponownym testem sprawdź w wygenerowanym AndroidManifest.xml pole android:usesCleartextTraffic, bo przeładowanie samym JS zachowuje stary manifest. Dopasuj wersję pluginu do Expo SDK, na którym działa projekt. Opcje pluginu zmieniają się między wydaniami, a fragment skopiowany z innego SDK jest pewnym źródłem cichych no-opów.
Bare workflow i węższa opcja
Dla bare React Native odpowiednikiem jest android:usesCleartextTraffic na elemencie application albo konfiguracja bezpieczeństwa sieci, która zezwala na cleartext tylko dla nazwanych domen. Forma ograniczona do domen jest tą, którą warto preferować, bo dopuszcza wewnętrzne API, a wszystko inne zostawia na HTTPS. Dokumentuje też własną listę wyjątków, i właśnie o tę część zapyta recenzent.
Żadne z tych podejść nie zmienia domyślnego zachowania platformy dla czegokolwiek, czego nie nazwałeś.
Najpierw udowodnij to z logu urządzenia
Przed edycją konfiguracji zdobądź dokładny błąd. adb logcat na podłączonym urządzeniu pokazuje odrzucenie cleartext przez platformę i nazywa komponent, który je wywołał. Odrzucony socket, nazwa, której nie da się rozwiązać, albo nieudany uścisk dłoni TLS wskazują zupełnie gdzie indziej, a włączenie cleartext tylko niepotrzebnie osłabiłoby aplikację.
Potem utrzymuj produkcję uczciwie. Cleartext jest dopuszczalny dla laboratoryjnego endpointu, który nie może zaoferować TLS, i tylko przez najkrótszy czas, jaki da się zaplanować. Jeśli API może zakończyć TLS wewnątrz sieci prywatnej, umieść certyfikat w magazynie zaufania urządzenia i pozostaw cleartext wyłączony, bo tunel szyfruje drogę do swojego wyjścia i nic poza nim.
Gdy endpoint zacznie odpowiadać po HTTPS, usuń uprawnienie, zbuduj ponownie i przetestuj na VPN oraz na zwykłym Wi-Fi w tej samej sesji. Rozwiązywanie nazw może się różnić na tych dwóch drogach, i tylko para mówi, która mówi prawdę.