在ReactNative应用中使用fetch API时如何忽略自签名SSL证书的错误?

23

我正在构建一个小的ReactNative iOS应用程序。 在其中,我使用fetch API向我控制的服务器发出简单的get请求,该服务器具有有效但自签名的SSL证书。可以理解的是,这会引起错误。

在iOS/JSC之间,我不确定如何(或者说哪些配置)可以使我的应用程序忽略此错误 - 到目前为止,我找到的所有答案都与Objective-C解决方案有关,我正在寻找一些我可以在JSC环境中使用的东西。

3个回答

14

我也遇到了同样的问题。正如你所说,似乎让自签名证书与本地iOS应用一起工作的唯一方法是编写/修改Objective-C代码,但对于使用React Native的JavaScript开发人员而言,这并不是一个好的方法。因此,我认为你的问题是一个X/Y问题,我建议从根本上解决你的问题,而不是首先使用自签名证书。

我使用真实证书进行开发。以下是我为使我的本地开发API与SSL和React Native一起工作所做的事情。它是免费且简单的。

  • ssh进入与您的域名关联的公共服务器
  • 安装Let's Encrypt
  • 为您的开发子域生成证书
    • dev.my-domain.com用于在本地开发我的网站/ webapp
    • api.dev.my-domain.com用于API
    • ./letsencrypt-auto certonly --standalone -d dev.my-domain.com -d api.dev.my-domain.com
  • 将fullchain.pem和privkey.pem复制到本地机器
    • 可能在/etc/letsencrypt/live/dev.my-domain.com下找到
    • 从远程机器获取文件的一种方法:scp -r your_user@123.123.(...):/etc/letsencrypt/live/dev.my-domain.com ./
  • 将您的自签名证书替换为fullchain.pem和privkey.pem
  • 将dev.your-domain.com和其他子域指向您的开发机器的IP
    • 您可以在每台想使用该域的计算机上修改hosts文件
    • 如果您的路由器有dnsmasq,则可以执行类似于address=/dev.my-domain.com/192.168.(...)的操作以获得整个网络(我建议这样做)

此时,因为您正在使用实际的、可信的域名证书进行访问,所以您的API现在在开发中的浏览器和设备中将被信任!


4
请注意,Let's Encrypt 无法为内部服务器提供工作,这些服务器无法公开访问(例如在 vagrant 环境中运行的服务器)。 - IanVS
这在生产环境中的工作方式有何不同?移动设备/客户端不需要任何特殊的东西,对吗? - ryanwebjackson
@ryanwebjackson,这个解决方案假设您在开发过程中使用了不同的域名/IP/URL,而不是指向您的生产服务器,因为在这种情况下,开发过程中不需要SSL证书。 - m59
1
@Max 我喜欢自动化它。我在生产服务器上运行一个Docker服务,用于更新生产服务器和开发证书,然后它会提交开发证书到Git,这样只需简单的git pull就可以在本地使用了。 - m59
我问了一个与此特定相关的问题,但目前还没有人回答:https://stackoverflow.com/questions/66608981/can-i-make-a-dev-ssl-certificate-public-if-not-how-do-i-distribute-the-certific - Max
显示剩余4条评论

10

免责声明:这个解决方案应该是暂时的并且需要记录,以便它不会停留在软件的生产阶段,这只适用于开发。

对于iOS,你只需要打开你的xcodeproject(在RN文件夹内),一旦打开,进入RCTNetwork.xcodeproj,在该项目中,导航到RCTHTTPRequestHandler.m

在那个文件中,你会看到一行像这样:

 #pragma mark - NSURLSession delegate

在那一行的下面,添加这个函数

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

现在你可以不使用有效证书就对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>

对于一个真正的投入生产的解决方案,https://dev59.com/MFwY5IYBdhLWcg3wM1bK#36368360 那个解决方案更好。


除了存在严重的不安全因素外,如果您的服务需要任何HTTP认证,该方法也会以奇怪的方式失败。要了解更安全的解决方案(不必是临时的),请阅读苹果开发者文库中的https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/NetworkingTopics/Articles/OverridingSSLChainValidationCorrectly.html。 - dgatwood
我会直接复制粘贴这个,因为你可能错过了它。免责声明:此解决方案应该是临时的,并且应该记录下来,以便它不会留在软件的生产阶段中,这仅用于开发。 - Santiago Jimenez Wilson
3
暂时解决方案的问题在于,根据我的经验它们往往会被最终推出。这就是为什么我从不建议暂时采用这种方式。无论如何,至少应该使用#if DEBUG将代码片段包含起来。 :-) - dgatwood
我同意... 我们这些开发人员有时会忘记我们有多么健忘。仔细想想,你指出的是一些很实在的建议。 - Santiago Jimenez Wilson
1
这是一个 Git 补丁,用于第一个示例的答案,它信任 react-native 请求的所有证书: https://gist.githubusercontent.com/aleclarson/2bd4347a54d08d2abcbb96ebbb573070/raw/956cf3e2d7cd1ce1d0cb93671db5bb10496feb39/ssl-dev.patch - aleclarson

-4

这个答案适用于Android。

  1. node_modules\react-native\ReactAndroid\src\main\java\com\facebook\react\modules\network 找到 OkHttpClientProvider.java 文件。

  2. 使用 NDK 编译 ReactAndroid。


编译ReactAndroid需要使用NDK吗?您能更详细地解释一下吗? - Sujit
@Sujit 如果你不构建它,修改后的代码可能无法工作。 - Bruce Lee
3
说明书中似乎缺少一个关键步骤。找到 OkHttpClientProvider.java 文件后,你该怎么做? - JJJ

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接