Skip to content

Commit aec2651

Browse files
jameshpcharafau
authored andcommitted
Add ignore ssl error parameter (#590)
* add ignoreSSLErrors parameter - just Android * iOS implementation to allow ignore SSL Errors * add documentation for ignoreSSLErrorsFlag * remove log messages used for ignorSSLErrors debug
1 parent fee1fee commit aec2651

File tree

9 files changed

+184
-121
lines changed

9 files changed

+184
-121
lines changed

README.md

Lines changed: 50 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,32 @@ Set the `withLocalUrl` option to true in the launch function or in the Webview s
166166

167167
Note that, on iOS, the `localUrlScope` option also needs to be set to a path to a directory. All files inside this folder (or subfolder) will be allowed access. If ommited, only the local file being opened will have access allowed, resulting in no subresources being loaded. This option is ignored on Android.
168168

169+
### Ignoring SSL Errors
170+
171+
Set the `ignoreSSLErrors` option to true to display content from servers with certificates usually not trusted by the Webview like self-signed certificates.
172+
173+
**_Warning:_** Don't use this in production.
174+
175+
Note that on iOS you you need to add new key to `ios/Runner/Info.plist`
176+
177+
```xml
178+
<key>NSAppTransportSecurity</key>
179+
<dict>
180+
<key>NSAllowsArbitraryLoads</key>
181+
<true/>
182+
<key>NSAllowsArbitraryLoadsInWebContent</key>
183+
<true/>
184+
</dict>
185+
```
186+
187+
`NSAllowsArbitraryLoadsInWebContent` is for iOS 10+ and `NSAllowsArbitraryLoads` for iOS 9.
188+
Otherwise you'll still not be able to display content from pages with untrusted certificates.
189+
190+
You can test your ignorance of ssl certificates is working e.g. through https://self-signed.badssl.com/
191+
192+
193+
194+
169195
### Webview Events
170196

171197
- `Stream<Null>` onDestroy
@@ -182,25 +208,30 @@ Note that, on iOS, the `localUrlScope` option also needs to be set to a path to
182208

183209
```dart
184210
Future<Null> launch(String url, {
185-
Map<String, String> headers: null,
186-
bool withJavascript: true,
187-
bool clearCache: false,
188-
bool clearCookies: false,
189-
bool hidden: false,
190-
bool enableAppScheme: true,
191-
Rect rect: null,
192-
String userAgent: null,
193-
bool withZoom: false,
194-
bool withLocalStorage: true,
195-
bool withLocalUrl: true,
196-
String localUrlScope: null,
197-
bool scrollBar: true,
198-
bool supportMultipleWindows: false,
199-
bool appCacheEnabled: false,
200-
bool allowFileURLs: false,
201-
bool displayZoomControls: false,
202-
bool useWideViewPort: false,
203-
bool withOverviewMode: false,
211+
Map<String, String> headers: null,
212+
Set<JavascriptChannel> javascriptChannels: null,
213+
bool withJavascript: true,
214+
bool clearCache: false,
215+
bool clearCookies: false,
216+
bool hidden: false,
217+
bool enableAppScheme: true,
218+
Rect rect: null,
219+
String userAgent: null,
220+
bool withZoom: false,
221+
bool displayZoomControls: false,
222+
bool withLocalStorage: true,
223+
bool withLocalUrl: true,
224+
String localUrlScope: null,
225+
bool withOverviewMode: false,
226+
bool scrollBar: true,
227+
bool supportMultipleWindows: false,
228+
bool appCacheEnabled: false,
229+
bool allowFileURLs: false,
230+
bool useWideViewPort: false,
231+
String invalidUrlRegex: null,
232+
bool geolocationEnabled: false,
233+
bool debuggingEnabled: false,
234+
bool ignoreSSLErrors: false,
204235
});
205236
```
206237

android/flutter_webview_plugin.iml

Lines changed: 83 additions & 92 deletions
Large diffs are not rendered by default.

android/src/main/java/com/flutter_webview_plugin/FlutterWebviewPlugin.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ void openUrl(MethodCall call, MethodChannel.Result result) {
126126
String invalidUrlRegex = call.argument("invalidUrlRegex");
127127
boolean geolocationEnabled = call.argument("geolocationEnabled");
128128
boolean debuggingEnabled = call.argument("debuggingEnabled");
129+
boolean ignoreSSLErrors = call.argument("ignoreSSLErrors");
129130

130131
if (webViewManager == null || webViewManager.closed == true) {
131132
Map<String, Object> arguments = (Map<String, Object>) call.arguments;
@@ -158,7 +159,8 @@ void openUrl(MethodCall call, MethodChannel.Result result) {
158159
useWideViewPort,
159160
invalidUrlRegex,
160161
geolocationEnabled,
161-
debuggingEnabled
162+
debuggingEnabled,
163+
ignoreSSLErrors
162164
);
163165
result.success(null);
164166
}

android/src/main/java/com/flutter_webview_plugin/WebviewManager.java

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@
55
import android.annotation.TargetApi;
66
import android.app.Activity;
77
import android.content.Context;
8+
import android.net.http.SslError;
89
import android.os.Build;
910
import android.os.Handler;
1011
import android.view.KeyEvent;
1112
import android.view.View;
1213
import android.view.ViewGroup;
1314
import android.webkit.CookieManager;
1415
import android.webkit.GeolocationPermissions;
16+
import android.webkit.SslErrorHandler;
1517
import android.webkit.ValueCallback;
1618
import android.webkit.WebChromeClient;
1719
import android.webkit.WebSettings;
@@ -123,14 +125,24 @@ private Uri[] getSelectedFiles(Intent data) {
123125
BrowserClient webViewClient;
124126
ResultHandler resultHandler;
125127
Context context;
128+
private boolean ignoreSSLErrors = false;
126129

127130
WebviewManager(final Activity activity, final Context context, final List<String> channelNames) {
128131
this.webView = new ObservableWebView(activity);
129132
this.activity = activity;
130133
this.context = context;
131134
this.resultHandler = new ResultHandler();
132135
this.platformThreadHandler = new Handler(context.getMainLooper());
133-
webViewClient = new BrowserClient();
136+
webViewClient = new BrowserClient() {
137+
@Override
138+
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
139+
if (ignoreSSLErrors){
140+
handler.proceed();
141+
}else {
142+
super.onReceivedSslError(view, handler, error);
143+
}
144+
}
145+
};
134146
webView.setOnKeyListener(new View.OnKeyListener() {
135147
@Override
136148
public boolean onKey(View v, int keyCode, KeyEvent event) {
@@ -241,6 +253,7 @@ public boolean onShowFileChooser(
241253
return true;
242254
}
243255

256+
244257
@Override
245258
public void onProgressChanged(WebView view, int progress) {
246259
Map<String, Object> args = new HashMap<>();
@@ -365,7 +378,8 @@ void openUrl(
365378
boolean useWideViewPort,
366379
String invalidUrlRegex,
367380
boolean geolocationEnabled,
368-
boolean debuggingEnabled
381+
boolean debuggingEnabled,
382+
boolean ignoreSSLErrors
369383
) {
370384
webView.getSettings().setJavaScriptEnabled(withJavascript);
371385
webView.getSettings().setBuiltInZoomControls(withZoom);
@@ -388,6 +402,8 @@ void openUrl(
388402
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
389403
webView.setWebContentsDebuggingEnabled(debuggingEnabled);
390404
}
405+
//ignore SSL errors
406+
this.ignoreSSLErrors = ignoreSSLErrors;
391407

392408
webViewClient.updateInvalidUrlRegex(invalidUrlRegex);
393409

example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@
2727
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
2828
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
2929
shouldUseLaunchSchemeArgsEnv = "YES">
30-
<Testables>
31-
</Testables>
3230
<MacroExpansion>
3331
<BuildableReference
3432
BuildableIdentifier = "primary"
@@ -38,8 +36,8 @@
3836
ReferencedContainer = "container:Runner.xcodeproj">
3937
</BuildableReference>
4038
</MacroExpansion>
41-
<AdditionalOptions>
42-
</AdditionalOptions>
39+
<Testables>
40+
</Testables>
4341
</TestAction>
4442
<LaunchAction
4543
buildConfiguration = "Debug"
@@ -61,8 +59,6 @@
6159
ReferencedContainer = "container:Runner.xcodeproj">
6260
</BuildableReference>
6361
</BuildableProductRunnable>
64-
<AdditionalOptions>
65-
</AdditionalOptions>
6662
</LaunchAction>
6763
<ProfileAction
6864
buildConfiguration = "Release"

example/ios/Runner/Info.plist

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,5 +41,10 @@
4141
</array>
4242
<key>UIViewControllerBasedStatusBarAppearance</key>
4343
<false/>
44+
<key>NSAppTransportSecurity</key>
45+
<dict>
46+
<key>NSAllowsArbitraryLoadsInWebContent</key>
47+
<true/>
48+
</dict>
4449
</dict>
4550
</plist>

ios/Classes/FlutterWebviewPlugin.m

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ @interface FlutterWebviewPlugin() <WKNavigationDelegate, UIScrollViewDelegate, W
99
BOOL _enableZoom;
1010
NSString* _invalidUrlRegex;
1111
NSMutableSet* _javaScriptChannelNames;
12+
NSNumber* _ignoreSSLErrors;
1213
}
1314
@end
1415

@@ -94,7 +95,7 @@ - (void)initWebview:(FlutterMethodCall*)call withResult:(FlutterResult)result {
9495
NSNumber *scrollBar = call.arguments[@"scrollBar"];
9596
NSNumber *withJavascript = call.arguments[@"withJavascript"];
9697
_invalidUrlRegex = call.arguments[@"invalidUrlRegex"];
97-
98+
_ignoreSSLErrors = call.arguments[@"ignoreSSLErrors"];
9899
_javaScriptChannelNames = [[NSMutableSet alloc] init];
99100

100101
WKUserContentController* userContentController = [[WKUserContentController alloc] init];
@@ -160,6 +161,21 @@ - (void)initWebview:(FlutterMethodCall*)call withResult:(FlutterResult)result {
160161
[self navigate:call];
161162
}
162163

164+
- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler {
165+
if ([_ignoreSSLErrors boolValue]){
166+
SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;
167+
CFDataRef exceptions = SecTrustCopyExceptions(serverTrust);
168+
SecTrustSetExceptions(serverTrust, exceptions);
169+
CFRelease(exceptions);
170+
completionHandler(NSURLSessionAuthChallengeUseCredential,
171+
[NSURLCredential credentialForTrust:serverTrust]);
172+
}
173+
else {
174+
completionHandler(NSURLSessionAuthChallengePerformDefaultHandling,nil);
175+
}
176+
177+
}
178+
163179
- (CGRect)parseRect:(NSDictionary *)rect {
164180
return CGRectMake([[rect valueForKey:@"left"] doubleValue],
165181
[[rect valueForKey:@"top"] doubleValue],

lib/src/base.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ class FlutterWebviewPlugin {
140140
/// - [displayZoomControls]: display zoom controls on webview
141141
/// - [withOverviewMode]: enable overview mode for Android webview ( setLoadWithOverviewMode )
142142
/// - [useWideViewPort]: use wide viewport for Android webview ( setUseWideViewPort )
143+
/// - [ignoreSSLErrors]: use to bypass Android/iOS SSL checks e.g. for self-signed certificates
143144
Future<Null> launch(
144145
String url, {
145146
Map<String, String> headers,
@@ -165,6 +166,7 @@ class FlutterWebviewPlugin {
165166
String invalidUrlRegex,
166167
bool geolocationEnabled,
167168
bool debuggingEnabled,
169+
bool ignoreSSLErrors,
168170
}) async {
169171
final args = <String, dynamic>{
170172
'url': url,
@@ -188,6 +190,7 @@ class FlutterWebviewPlugin {
188190
'geolocationEnabled': geolocationEnabled ?? false,
189191
'withOverviewMode': withOverviewMode ?? false,
190192
'debuggingEnabled': debuggingEnabled ?? false,
193+
'ignoreSSLErrors': ignoreSSLErrors ?? false,
191194
};
192195

193196
if (headers != null) {

lib/src/webview_scaffold.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class WebviewScaffold extends StatefulWidget {
3939
this.invalidUrlRegex,
4040
this.geolocationEnabled,
4141
this.debuggingEnabled = false,
42+
this.ignoreSSLErrors = false,
4243
}) : super(key: key);
4344

4445
final PreferredSizeWidget appBar;
@@ -70,6 +71,7 @@ class WebviewScaffold extends StatefulWidget {
7071
final bool withOverviewMode;
7172
final bool useWideViewPort;
7273
final bool debuggingEnabled;
74+
final bool ignoreSSLErrors;
7375

7476
@override
7577
_WebviewScaffoldState createState() => _WebviewScaffoldState();
@@ -174,6 +176,7 @@ class _WebviewScaffoldState extends State<WebviewScaffold> {
174176
invalidUrlRegex: widget.invalidUrlRegex,
175177
geolocationEnabled: widget.geolocationEnabled,
176178
debuggingEnabled: widget.debuggingEnabled,
179+
ignoreSSLErrors: widget.ignoreSSLErrors,
177180
);
178181
} else {
179182
if (_rect != value) {

0 commit comments

Comments
 (0)