Solución:
Descargo de responsabilidad: esta solución debe ser temporal y estar documentada para que no permanezca en la fase de producción del software, esto es solo para desarrollo.
Para iOS, todo lo que tiene que hacer es abrir su xcodeproject (dentro de su carpeta iOS en RN) una vez que lo tenga abierto, vaya a RCTNetwork.xcodeproj y en ese proyecto, navegue a RCTHTTPRequestHandler.m
En ese archivo verá una línea como esta:
#pragma mark - NSURLSession delegate
justo después de esa línea, agregue esta función
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler
{
completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
}
Y listo, ahora puede realizar llamadas inseguras a su API sin un certificado válido.
Eso debería ser suficiente, pero si sigues teniendo problemas, es posible que debas ir al info.plist de tu proyecto, hacer clic izquierdo en él y elegir abrir como … código fuente.
y al final solo agrega
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>NSExceptionDomains</key>
<dict>
<key>localhost</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
<key>subdomain.example.com</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
para que su archivo se vea así
...
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>NSLocationWhenInUseUsageDescription</key>
<string></string>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>NSExceptionDomains</key>
<dict>
<key>localhost</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
<key>subdomain.example.com</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
</plist>
Para obtener una solución real lista para la producción, https://stackoverflow.com/a/36368360/5943130 esa solución es mejor
También me enfrento al mismo problema en Android. Finalmente encontré la solución para este problema.
import com.facebook.react.modules.network.OkHttpClientFactory;
import com.facebook.react.modules.network.OkHttpClientFactory;
import com.facebook.react.modules.network.OkHttpClientProvider;
import com.facebook.react.modules.network.ReactCookieJarContainer;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import okhttp3.CipherSuite;
import okhttp3.ConnectionSpec;
import okhttp3.OkHttpClient;
import okhttp3.TlsVersion;
import static android.content.ContentValues.TAG;
public class CustomClientFactory implements OkHttpClientFactory {
private static final String TAG = "OkHttpClientFactory";
@Override
public OkHttpClient createNewNetworkModuleClient() {
try {
// Create a trust manager that does not validate certificate chains
final TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[]{};
}
}
};
// Install the all-trusting trust manager
final SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
// Create an ssl socket factory with our all-trusting manager
final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
OkHttpClient.Builder builder = new OkHttpClient.Builder()
.connectTimeout(0, TimeUnit.MILLISECONDS).readTimeout(0, TimeUnit.MILLISECONDS)
.writeTimeout(0, TimeUnit.MILLISECONDS).cookieJar(new ReactCookieJarContainer());
builder.sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0]);
builder.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
OkHttpClient okHttpClient = builder.build();
return okHttpClient;
} catch (Exception e) {
Log.e(TAG, e.getMessage());
throw new RuntimeException(e);
}
}
}
y dentro de nuestra aplicación de Android MainApplication.java
@Override
public void onCreate() {
super.onCreate();
SoLoader.init(this, /* native exopackage */ false);
OkHttpClientProvider.setOkHttpClientFactory(new CustomClientFactory()); //add this line.
}
Es un trabajo para mi. Puede que ayude a todos.
Conseguí que esto funcionara en Android haciendo lo siguiente:
- Instale la CA en su dispositivo en Configuración -> Seguridad y ubicación> Avanzado> Cifrado y credenciales> Instalar desde almacenamiento. Puede confirmar que está instalado correctamente visitando el dominio a través de un navegador web en su dispositivo. Si el certificado se valida, entonces la CA está instalada.
- Cree una configuración de seguridad de red en
res/xml/network_security_config.xml
con los siguientes contenidos. Actualice los dominios.
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<!-- For React Native Hot-reloading system -->
<!-- If you are running on a device insert your computer IP -->
<domain includeSubdomains="true">localhost</domain>
<domain includeSubdomains="true">your self signed domain</domain>
<trust-anchors>
<certificates src="https://foroayuda.es/system" />
<certificates src="user" />
</trust-anchors>
</domain-config>
<base-config cleartextTrafficPermitted="false" />
</network-security-config>
- Haga referencia a este archivo de configuración de su
AndroidManifest.xml
.
<?xml version="1.0" encoding="utf-8"?>
<manifest ... >
<application android:networkSecurityConfig="@xml/network_security_config"
... >
...
</application>
</manifest>