Подтвердить что ты не робот

React-native fetch() с сервера https с самозаверяющим сертификатом

Я пытаюсь связаться с сервером https с самозаверяющим сертификатом.

Я могу сделать это из приложения .NET(используя событие ServicePointManager.ServerCertificateValidationCallback), из приложения native iOs (используя allowAnyHTTPSCertificateForHost) или из веб-браузера (просто нужно объявить, что сертификат доверен).

Но я не могу заставить его работать в реактивном приложении (ни в Android, ни в iOS-симуляторе).

Я пробовал разные вещи, но все равно не получился.

Я знаю, что есть похожие темы:
Игнорировать ошибки для самоподписанных сертификатов SSL, используя API-интерфейс Fetch в приложении ReactNative?
Отменить собственный запрос XMLHttpRequest, если сертификат ssl (https) недействителен
Взаимодействие с родной неработающей работой с ssl на android
Проблемы с получением данных с сервера на основе SSL
Невозможно выполнить вызовы API с использованием адаптивного интерфейса

Но они либо не содержат ответов, либо не работают (и вообще не занимаются программированием на Android). Поиск других ресурсов также не был продуктивным.

Я считаю, что должен быть простой способ работать с самозаверяющим сертификатом. Я ошибаюсь? Кто-нибудь знает это (как для iOS, так и для Android)?

4b9b3361

Ответ 1

Отказ от ответственности: это решение должно быть временным и документированным, чтобы оно не оставалось на стадии производства программного обеспечения, это только для разработки.

Для iOS все, что вам нужно сделать, - откройте свой xcodeproject (внутри вашей папки iOS в RN), как только вы откроете это, перейдите в RCTNetwork.xcodeproj и в этом проекте перейдите к RCTHTTPRequestHandler.m

В этом файле вы увидите следующую строку:

#pragma mark - NSURLSession delegate

сразу после этой строки добавьте эту функцию

- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler
{
  completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
}

И теперь вы можете сделать небезопасные вызовы для вашего API без действительного сертификата.

Этого должно быть достаточно, но если у вас все еще есть проблемы, вам может потребоваться перейти к вашему проекту info.plist, щелкнуть левой кнопкой мыши по нему и выбрать открытый как... исходный код.

и в конце просто добавьте

<key>NSAppTransportSecurity</key>
  <dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
  </dict>

поэтому ваш файл будет выглядеть следующим образом

    ...
    <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>
</dict>
</plist>

Для реального готового решения для производства fooobar.com/questions/333876/... это решение лучше

Ответ 2

Пиггингация @Сантьяго Хименес Уилсон ответит здесь.

Очевидно, что patch-response-native сам по себе довольно грязный, поэтому мы приняли предложенное переопределение и извлекли его в категорию.

Просто создайте новый файл с именем RCTHTTPRequestHandler+yourPatchName.m где-то в вашем проекте:

//
//  RCTHTTPRequestHandler+yourPatchName
//

#import "RCTBridgeModule.h"
#import "RCTHTTPRequestHandler.h"

@implementation RCTHTTPRequestHandler(yourPatchName)

- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler
{
  completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
}
@end

Следующий шаг должен был бы тогда отличаться между dev и prod и только перегружать метод для dev.

Ответ 3

Это происходит из-за самозаверяющего сертификата, используемого для шифрования. Из-за соображений безопасности в Android он требует от центра сертификации подписанных или доверенных сертификатов.

используйте этот плагин, чтобы избежать этого.

https://www.npmjs.com/package/react-native-fetch-blob

RNFetchBlob.config({
  trusty : true
})
.then('GET', 'https://xxxxx.com')
.then((resp) => {
  // ...
})

Добавьте config trusty как true, чтобы доверять сертификату, когда вы используете POST или GET API

Ответ 4

Я получил это работает на Android, выполнив следующие действия:

  1. Установите ЦС на устройстве в разделе "Настройки" → "Безопасность и местоположение"> "Дополнительно"> "Шифрование и учетные данные"> "Установить из хранилища". Вы можете подтвердить правильность установки, посетив домен через веб-браузер на вашем устройстве. Если сертификат действителен, то CA установлен.
  2. Создайте конфигурацию безопасности сети по адресу res/xml/network_security_config.xml со следующим содержимым. Обновите домен (ы).
<?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="system" />
            <certificates src="user" />
        </trust-anchors>
    </domain-config>

    <base-config cleartextTrafficPermitted="false" />
</network-security-config>
  1. Ссылка на этот файл конфигурации из вашего AndroidManifest.xml.
<?xml version="1.0" encoding="utf-8"?>
<manifest ... >
    <application android:networkSecurityConfig="@xml/network_security_config"
                    ... >
        ...
    </application>
</manifest>

Ответ 5

Просто чтобы добавить информацию для пользователей, которые ищут Android Solution. Как реагирующая система не обрабатывает ошибку SSL по умолчанию. Существует простой подход к запуску WebView для веб-сайтов, которые должны быть подключены через "https" вместо "http".

Я предполагаю, что вы уже установили модульact-native-webview с помощью NPM, если нет, то, пожалуйста, Google.

Как только у вас есть модуль "response-native-webview" внутри папки "node_modules". Зайдите внутрь ".\Node_modules >> Reaction-native-webview >> android >> src >> main >> java >> com >> реагировать на общение >> webview"

Откройте файл "RNCWebViewManager.java" в текстовом редакторе и добавьте следующий код

В разделе импорта добавьте эти две зависимости

....
import android.webkit.SslErrorHandler;
import android.net.http.SslError;
....

Теперь поиск ниже "class" внутри того же файла защищен статическим классом. RNCWebViewClient расширяет WebViewClient

И добавить этот метод

@Override
public void onReceivedSslError(WebView webView, SslErrorHandler handler, SslError 
error) {
    if (error.toString() == "piglet")
        handler.cancel();
    else
        handler.proceed(); // Ignore SSL certificate errors
}

Далее сохраните файл и постройте свой проект. Он не будет отображать пустую страницу сейчас и обработать неверную ошибку SSL.

Замечания:

  1. Решение работает, только если вы используете "WebView" из "act-native-webview "вместо устаревшего" WebView "из "act-native"
  2. Убедитесь, что вы уже связали свой "response-native" с "response-native-webview", иначе он не будет включен в ваш проект Android
  3. В классах "RNCWebViewModule", "RNCWebViewManager", "RNCWebViewFileProvider" может быть ошибка Error (будет отображаться, как только вы правильно создадите свой проект с использованием react-native run-android реакции в AndroidStudio после открытия проекта Android с помощью импорта), который можно легко исправить используя AndroidStudio