一、问题描述
Flutter项目使用谷歌官方webview库 webview_flutter,加载自签名证书、证书失效、无证书等HTTPS网页地址时,在Android或pc浏览器中提示证书失效,在iOS设备上为空白页,为了加载自签名证书的网页,需要饶过iOS上的webview控件HTTPS证书校验。
二、环境
Android Studio版本:2022.1.1 Patch 2
Flutter版本:3.7.12
Dart SDK版本:2.19.6
依赖库 webview_flutter 版本:4.2.0
Xcode版本:14.3
三、Flutter中解决iOS设备上HTTPS证书校验方案
1、添加webview_flutter版本库依赖
在pubspec.yaml文件中,找到dev_dependencies,然后换行添加依赖库,添加完运行命令【flutter pub get】,下载该库。
dev_dependencies:
webview_flutter: ^4.2.0
下载完成后在项目结构External Libraries下,可以看到webview_flutter一共下载了三个项目,分别是webview_flutter-4.2.0、webview_flutter_android-3.7.0、webview_flutter_wkwebview-3.4.3,其中webview_flutter_wkwebview-3.4.3为iOS设备上的一个webview组件,后面所要修改源码的也就是这个工程。
2、修改源码
在Flutter工程目录结构中找到 External Libraries,依次展开Flutter Plugins——>webview_flutter_wkwebview-3.4.3——>ios.Classes
然后在ios.Classes目录下,找到FWFNavigationDelegateHostApi.m文件,打开该文件,在 @implementation FWFNavigationDelegate 代码以后换行添加以下方法:
@implementation FWFNavigationDelegate
//复制添加这个方法
- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler{
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;
// 在这里进行自定义的身份验证逻辑
NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust];
completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
} else {
completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
}
}
然后保存,再次运行即可。
注:因为该修改方式只是将本地的webview_flutter库源码做修改,要想应用到其他人的项目当中,需要把该 webview_flutter_wkwebview-3.4.3库导出上传到GitHub或者Gitee仓库,然后通过在pubspec.yaml文件中添加依赖库覆盖原webview_flutter库源码的方式,才能正确应用到其他人的项目中。导出方式:点击该库然后鼠标右键,找到 Open in——>Finder,打开即是。
3、覆盖原库
具体流程如下:
在pubspec.yaml文件中,找到 dependency_overrides:节点,然后在其下方换行添加以下内容:
dependency_overrides:
#注意这里不要顶格,格式务必确认正确,url地址为你自己修改过的源码库地址,
webview_flutter_wkwebview:
git:
url: https://gitee.com/user/webview_flutter_wkwebview-3.4.3.git
然后在项目根目录下,运行【flutter pub get】命令,会提示输入你源码所在仓库的用户名和密码,下载完成后就能看到源码库名称已经变为你自己的仓库名称了。
四、Xcode原生工程解决iOS设备上HTTPS证书校验方案
1、导入WKWebview库
在Xcode项目中,找到General界面,在其下方界面找到【Frameworks,Libraries,and Embedded Content】,点击右侧的加号➕按钮,在弹出的搜索界面,搜索WebKit,然后选中搜索出来的WebKit.framework库,点击下面的Add按钮,WKWebview依赖库添加完成。
2、添加代码
#import "ViewController.h"
#import <WebKit/WebKit.h>
//1、这里添加WKNavigationDelegate接口,为了实现WKWebView的证书校验方法
@interface ViewController () <WKNavigationDelegate>
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//添加webview组件
WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
CGRect frame = CGRectMake(0, 170, 400, 800);
WKWebView *webView = [[WKWebView alloc] initWithFrame:frame configuration:configuration];
[self.view addSubview:webView];
NSURL *url = [NSURL URLWithString:@"https://www.baidu.com"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
//开始加载网页地址
[webView loadRequest:request];
//2、将当前类与WKNavigationDelegate接口监听进行绑定
webView.navigationDelegate = self;
}
//3、重写didReceiveAuthenticationChallenge方法
- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler{
//在该方法当中添加如下代码,
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;
NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust];
completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
} else {
completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
}
}
@end
代码一共分为三步,添加完即可实现饶过HTTPS网页证书校验问题。
五、Android设备上HTTPS证书校验解决方案
1、创建network_security_config.xml文件
在Android Studio中打开Flutter项目下的Android工程,然后在app的目录下,也就是项目的主module模块下,依次打开app——>src——>main——>res目录,在该目录下创建文件xml,然后在xml目录下,创建network_security_config.xml文件,文件内容如下:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
</network-security-config>
2、引用network_security_config.xml文件
在AndroidManifest.xml文件中,找到application节点,添加android:networkSecurityConfig属性
<application
android:networkSecurityConfig="@xml/network_security_config"
>
以上为在Android设备饶过HTTPS证书校验方案。