Connettersi ai servizi Web locali da simulatori iOS e emulatori Android
Molte applicazioni per dispositivi mobili utilizzano servizi Web. Durante la fase di sviluppo, è comune distribuire un servizio Web in locale e utilizzarlo da un'applicazione per dispositivi mobili in esecuzione nel simulatore iOS o nell'emulatore Android. Questo evita di dover distribuire il servizio Web a un endpoint ospitato e supporta una semplice esperienza di debug perché sia l'applicazione per dispositivi mobili che il servizio Web sono in esecuzione in locale.
Le applicazioni per dispositivi mobili in esecuzione nel simulatore iOS o nell'emulatore Android possono utilizzare servizi Web ASP.NET Core in esecuzione in locale ed esposti tramite HTTP, come indicato di seguito:
- Le applicazioni in esecuzione nel simulatore iOS possono connettersi ai servizi Web HTTP locali tramite l'indirizzo IP del computer o tramite il nome host
localhost
. Ad esempio, dato un servizio Web HTTP locale che espone un'operazione GET tramite l'URI relativo/api/todoitems/
, un'applicazione in esecuzione nel simulatore iOS può utilizzare l'operazione inviando una richiesta GET ahttp://localhost:<port>/api/todoitems/
. - Le applicazioni in esecuzione nell'emulatore Android possono connettersi ai servizi Web HTTP locali tramite l'indirizzo
10.0.2.2
, ovvero un alias per l'interfaccia di loopback host (127.0.0.1
nel computer di sviluppo). Ad esempio, dato un servizio Web HTTP locale che espone un'operazione GET tramite l'URI relativo/api/todoitems/
, un'applicazione in esecuzione nell'emulatore Android può utilizzare l'operazione inviando una richiesta GET ahttp://10.0.2.2:<port>/api/todoitems/
.
Sono necessari tuttavia altri interventi, affinché un'applicazione in esecuzione nel simulatore iOS o nell'emulatore Android possa utilizzare un servizio Web locale esposto tramite HTTPS. Per questo scenario, il processo è il seguente:
- Creare un certificato di sviluppo autofirmato nel computer. Per altre informazioni, vedere Creare un certificato di sviluppo.
- Configurare il progetto per usare lo stack di rete appropriato
HttpClient
per la compilazione di debug. Per altre informazioni, vedere Configurare il progetto. - Specificare l'indirizzo del computer locale. Per altre informazioni, vedere Specificare l'indirizzo del computer locale.
- Evitare il controllo di sicurezza del certificato di sviluppo locale. Per altre informazioni, vedere Evitare il controllo di sicurezza del certificato.
Ogni elemento verrà presentato singolarmente.
Creare un certificato di sviluppo
L'installazione di .NET Core SDK include l'installazione del certificato di sviluppo HTTPS ASP.NET Core nell'archivio certificati utente locale. Tuttavia, anche se il certificato viene installato, non è attendibile. Per rendere attendibile il certificato, seguire questa procedura una sola volta per eseguire lo strumento dev-certs
dotnet:
dotnet dev-certs https --trust
Il comando seguente consente di visualizzare informazioni della Guida sullo strumento dev-certs
:
dotnet dev-certs https --help
In alternativa, quando si esegue un progetto ASP.NET Core 2.1 (o versione successiva), che usa HTTPS, Visual Studio rileva se il certificato di sviluppo è mancante e offre di installarlo e impostarlo come attendibile.
Nota
Il certificato di sviluppo HTTPS ASP.NET Core è autofirmato.
Per altre informazioni sull'abilitazione di HTTPS locale nel computer, vedere Abilitare HTTPS locale.
Configurare il progetto
Le applicazioni Xamarin in esecuzione in iOS e Android possono specificare quale stack di rete viene usato dalla classe HttpClient
, scegliendo tra uno stack di rete gestito o stack di rete nativi. Lo stack gestito offre un alto elevato livello di compatibilità con il codice .NET esistente, ma è limitato a TLS 1.0 e può risultare più lento e comportare un aumento delle dimensioni del file eseguibile. Gli stack nativi possono essere più veloci e offrono maggiore sicurezza, ma potrebbero non fornire tutte le funzionalità della classe HttpClient
.
iOS
Le applicazioni Xamarin in esecuzione in iOS possono usare lo stack di rete gestito oppure gli stack di rete CFNetwork
o NSUrlSession
nativi. Per impostazione predefinita, i nuovi progetti per la piattaforma iOS usano lo stack di rete NSUrlSession
per supportare TLS 1.2 e usano le API native per migliorare le prestazioni e ottenere dimensioni dei file eseguibili più piccole. Per altre informazioni, vedere HttpClient e selettore dell'implementazione di SSL/TLS per iOS/macOS.
Android
Le applicazioni Xamarin in esecuzione in Android possono usare lo stack di rete gestito HttpClient
oppure lo stack di rete AndroidClientHandler
nativo. Per impostazione predefinita, i nuovi progetti per la piattaforma Android usano lo stack di rete AndroidClientHandler
per supportare TLS 1.2 e usano le API native per migliorare le prestazioni e ottenere dimensioni dei file eseguibili più piccole. Per altre informazioni sugli stack di rete Android, vedere HttpClient Stack and SSL/TLS Implementation selector for Android (Stack HttpClient e selettore di implementazione SSL/TLS per Android).
Specificare l'indirizzo del computer locale
Il simulatore iOS e l'emulatore Android consentono entrambi l'accesso ai servizi Web sicuri in esecuzione nel computer locale. Tuttavia, l'indirizzo del computer locale è diverso per ognuno.
iOS
Il simulatore iOS usa la rete del computer host. Le applicazioni in esecuzione nel simulatore possono quindi connettersi ai servizi Web in esecuzione nel computer locale tramite l'indirizzo IP del computer o tramite il nome host localhost
. Ad esempio, dato un servizio Web sicuro locale che espone un'operazione GET tramite l'URI relativo /api/todoitems/
, un'applicazione in esecuzione nel simulatore iOS può utilizzare l'operazione inviando una richiesta GET a https://localhost:<port>/api/todoitems/
.
Nota
Quando si esegue un'applicazione per dispositivi mobili nel simulatore iOS da Windows, l'applicazione viene visualizzata nel simulatore iOS remoto per Windows. Tuttavia, l'applicazione è in esecuzione nel Mac associato. Pertanto, non vi è alcun accesso tramite localhost a un servizio Web in esecuzione in Windows per un'applicazione iOS in esecuzione in un Mac.
Android
Ogni istanza dell'emulatore di Android è isolata dalle interfacce di rete del computer di sviluppo e viene eseguita dietro un router virtuale. Pertanto, un dispositivo emulato non può visualizzare il computer di sviluppo o altre istanze dell'emulatore in rete.
Tuttavia, il router virtuale per ogni emulatore gestisce uno spazio di rete speciale che include gli indirizzi già allocati, con l'indirizzo 10.0.2.2
usato come alias per l'interfaccia di loopback host (127.0.0.1 nel computer di sviluppo). Pertanto, dato un servizio Web sicuro locale che espone un'operazione GET tramite l'URI relativo /api/todoitems/
, un'applicazione in esecuzione nell'emulatore Android può utilizzare l'operazione inviando una richiesta GET a https://10.0.2.2:<port>/api/todoitems/
.
Rilevare il sistema operativo
La classe DeviceInfo
può essere usata per rilevare la piattaforma su cui è esecuzione l'applicazione. Il nome host appropriato, che consente l'accesso ai servizi Web sicuri locali, può quindi essere impostato come segue:
public static string BaseAddress =
DeviceInfo.Platform == DevicePlatform.Android ? "https://10.0.2.2:5001" : "https://localhost:5001";
public static string TodoItemsUrl = $"{BaseAddress}/api/todoitems/";
Per altre informazioni sulla DeviceInfo
classe , vedere Xamarin.Essentials: Informazioni sul dispositivo.
Evitare il controllo di sicurezza del certificato
Il tentativo di richiamare un servizio Web sicuro locale da un'applicazione in esecuzione nel simulatore iOS o nell'emulatore Android comporterà la generazione di una HttpRequestException
, anche quando si usa lo stack di rete gestito in ogni piattaforma. Questo avviene perché il certificato di sviluppo HTTPS locale è autofirmato e i certificati autofirmati non sono considerati attendibili da iOS o Android. Pertanto, è necessario ignorare gli errori SSL quando un'applicazione utilizza un servizio Web sicuro locale. Questa operazione può essere eseguita quando si usano gli stack di rete gestiti e nativi in iOS e Android impostando la ServerCertificateCustomValidationCallback
proprietà su un oggetto su un HttpClientHandler
callback che ignora il risultato del controllo di sicurezza del certificato per il certificato di sviluppo HTTPS locale:
// 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;
}
In questo esempio di codice, viene restituito il risultato della convalida del certificato server quando il certificato sottoposto a convalida non è il certificato localhost
. Per questo certificato, il risultato della convalida viene ignorato e viene restituito il valore true
, che indica che il certificato è valido. L'oggetto risultante HttpClientHandler
deve essere passato come argomento al HttpClient
costruttore per le compilazioni di debug:
#if DEBUG
HttpClientHandler insecureHandler = GetInsecureHandler();
HttpClient client = new HttpClient(insecureHandler);
#else
HttpClient client = new HttpClient();
#endif
Abilitare il traffico di testo non crittografato HTTP
Facoltativamente, è possibile configurare i progetti iOS e Android per consentire il traffico HTTP non crittografato. Se il servizio back-end è configurato per consentire il traffico HTTP, è possibile specificare HTTP negli URL di base e quindi configurare i progetti per consentire il traffico non crittografato:
public static string BaseAddress =
DeviceInfo.Platform == DevicePlatform.Android ? "http://10.0.2.2:5000" : "http://localhost:5000";
public static string TodoItemsUrl = $"{BaseAddress}/api/todoitems/";
Rifiuto esplicito di iOS ATS
Per abilitare il traffico locale non crittografato in iOS, è necessario rifiutare esplicitamente ATS aggiungendo quanto segue al file Info.plist :
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsLocalNetworking</key>
<true/>
</dict>
Configurazione della sicurezza di rete Android
Per abilitare il traffico locale in testo non crittografato in Android, è necessario creare una configurazione di sicurezza di rete aggiungendo un nuovo file XML denominato network_security_config.xml nella cartella Resources/xml . Il file XML deve specificare la configurazione seguente:
<?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>
Configurare quindi la proprietà networkSecurityConfig nel nodo applicazione nel manifesto Android:
<?xml version="1.0" encoding="utf-8"?>
<manifest>
<application android:networkSecurityConfig="@xml/network_security_config">
...
</application>
</manifest>
Assicurarsi che l'azione di compilazione sia impostata su AndroidResource. In caso contrario, il file XML non verrà trovato in fase di compilazione.