React native 使用自签名证书从https服务器响应本机获取()
我正在尝试与具有自签名证书的https服务器通信 我可以从.NET应用程序(使用ServicePointManager.ServerCertificateValidationCallback事件)、本机iOs应用程序(使用allowsAnyHTTPSCertificateForHost)或web浏览器(只需声明证书受信任)执行此操作 但我无法让它在react本机应用程序中工作(无论是在Android还是在iOS模拟器中) 我尝试过不同的事情,但仍然没有成功 我知道那里有一些类似的话题:React native 使用自签名证书从https服务器响应本机获取(),react-native,React Native,我正在尝试与具有自签名证书的https服务器通信 我可以从.NET应用程序(使用ServicePointManager.ServerCertificateValidationCallback事件)、本机iOs应用程序(使用allowsAnyHTTPSCertificateForHost)或web浏览器(只需声明证书受信任)执行此操作 但我无法让它在react本机应用程序中工作(无论是在Android还是在iOS模拟器中) 我尝试过不同的事情,但仍然没有成功 我知道那里有一些类似的话题:
但它们要么不包含答案,要么不起作用(而且它们根本不涉及android编程)。搜索其他资源也没有什么成效
我相信应该有一个简单的方法来使用自签名证书。我错了吗?有人知道吗(包括iOS和Android)?免责声明:此解决方案应该是临时的,并且有文档记录,这样它就不会停留在软件的生产阶段,这只是为了开发 对于iOS,您所要做的就是打开您的xcodeproject(在RN中的iOS文件夹中),打开后,转到RCTNetwork.xcodeproj,并在该项目中导航到RCTHTTPRequestHandler.m 在该文件中,您将看到如下行:
#pragma标记-NSURLSession委托
在该行之后添加此函数
-(void)URLSession:(NSURLSession*)session direceivechallenge:(nsurauthenticationchallenge*)challengecompletionhandler:(void(^)(NSURLSessionAuthChallengeDisposition disposition,NSURLCredential*credential))completionHandler
{
completionHandler(NSURLSessionAuthChallengeUseCredential,[nsurlCredentialCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
}
瞧,您现在可以在没有有效证书的情况下对API进行不安全的调用
这应该足够了,但如果您仍然有问题,您可能需要转到项目的info.plist,左键单击它并选择open as。。。源代码
最后再加上
NSAppTransportSecurity
NSAllowsArbitraryLoads
NSExceptionDomains
本地服务器
N异常低安全Http负载
subdomain.example.com
n包括多个域
N异常低安全Http负载
所以你的文件看起来像这样
。。。
UI支持接口方向
这个解决方案更好借鉴@Santiago Jimenez Wilson的答案
显然,修补react 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的方法。这是由于用于加密的自签名证书造成的。由于安卓系统中的安全原因,它需要授权机构签名或受信任的证书
使用此插件可以避免这种情况
将configtrusty添加为true以在发布或获取API时信任证书我通过以下操作在Android上实现了这一点:
在设备上的“设置”->“安全性和位置”->“高级”->“加密和凭据”->“从存储安装”下安装CA。您可以通过设备上的web浏览器访问域来确认已正确安装。如果证书验证,则安装CA
使用以下内容在res/xml/network\u security\u config.xml
创建网络安全配置。更新域
只是为寻找Android解决方案的用户添加信息。
默认情况下,作为react native不处理SSL错误。对于必须通过“https”而不是“http”连接的网站,有一种简单的方法来运行WebView
我假设您已经使用NPM安装了react native webview模块。如果没有,请使用google
一旦在“node_modules”文件夹中有了“react native webview”模块。
进去
“\node\u modules>>react native webview>>android>>src>>main>>java>>com>>react nativecommunity>>webview”
在文本编辑器中打开“RNCWebViewManager.java”文件并添加以下代码
在导入部分添加这两个依赖项
....
import android.webkit.SslErrorHandler;
import android.net.http.SslError;
....
现在在同一个文件中搜索下面的“类”
受保护的静态类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错误
注:
仅当您使用“react native WebView”中的“WebView”而不是“react native”中不推荐使用的“WebView”时,此解决方案才有效
确保您已经将“react native”与“react native webview”链接,否则它将不会包含在您的android项目中
“RNCWebViewModule”、“RNCWebViewManager”、“RNCWebViewFileProvider”类中可能存在版本错误(在使用导入打开android项目后,使用react native run android
在AndroidStudio内部正确构建项目后,将可见),您可以使用AndroidStudio轻松修复该错误
我在安卓系统中也面临同样的问题。最后我找到了解决这个问题的办法
import com.facebook.react.modules.network.OkHttpClientFactory;
导入com.facebook.react.modules.network.OkHttpClientFactory;
导入com.facebook.react.modules.network.OkHttpClientProvider;
导入com.facebook.react.modules.network.ReactCookieJarContainer;
导入java.security.cert.CertificateException;
导入java.util.ArrayList;
导入java.util.List;
导入java.util.concurrent.TimeUnit;
导入javax.net。
<?xml version="1.0" encoding="utf-8"?>
<manifest ... >
<application android:networkSecurityConfig="@xml/network_security_config"
... >
...
</application>
</manifest>
....
import android.webkit.SslErrorHandler;
import android.net.http.SslError;
....
@Override
public void onReceivedSslError(WebView webView, SslErrorHandler handler, SslError
error) {
if (error.toString() == "piglet")
handler.cancel();
else
handler.proceed(); // Ignore SSL certificate errors
}
* run this script normally for patching,
* pass -r argument at the end of the command for removing the patch
* ex:
* patching: $ node patch_ssl_bypass.js
* removing patch: $ node patch_ssl_bypass.js -r
*/
var fs = require('fs');
const isRemove = process.argv[process.argv.length-1] == '-r';
const file =
'node_modules/react-native/Libraries/Network/RCTHTTPRequestHandler.mm';
const delemeter = '#pragma mark - NSURLSession delegate';
const code = `
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler
{
completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
}
`;
console.log('############# Reading File ###############');
fs.readFile(file, 'utf8', function(error, data) {
if (error) {
console.log('############# error reading file ###############');
console.error(error);
return;
}
if (data.indexOf(code) < 0 && !isRemove) {
console.log('############# Patch is not done. ###############');
console.log('############# Patching file ###############');
var parts = data.split(delemeter);
var newCodeBlock = parts[0] + delemeter + '\n' + code + '\n'+parts[1];
fs.writeFile(file,newCodeBlock,function(){
console.log('############# Successfully patched file ###############');
console.log('############# re build the ios project ###############');
})
}else{
if (isRemove){
var updatedCode = data.replace(code,'');
fs.writeFile(file,updatedCode,function(){
console.log('############# Successfully removed patch ###############');
console.log('############# re build the ios project ###############');
})
}else{
console.log('############# File already patched. No need again ###############');
}
}
});