How to disable web security in iOS WKWebView? I used command "open /Applications/Google\ Chrome.app --args --disable-web-security --allow-file-access-from-files" in mac system to open the chrome. But How to do this in WKWebView? Thankes!
2 Answers
It's not possible to disable web security in WKWebView - there's no preference to do so - see the iOS source code for WebKit preferences.
There is a way to allow access from file URLs, although it's not officially supported. In the source code, a preference exists, so you can set it like this:
[wkWebView.configuration.preferences setValue:@TRUE forKey:@"allowFileAccessFromFileURLs"];
This enables access to file URLs relative to the content src. e.g. if the local page is foo/bar/index.html
you can access files in foo/bar/
(e.g. foo/bar/1.jpg
or foo/bar/sub/2.jpg
) but not outside (e.g. foo/other/3.jpg
or Documents/NoCloud/4.jpg
).
-
6Do you know if this would be accepted in the appStore ? – cromanelli May 11 '17 at 20:00
-
1I don't see why not. If it were possible to disable web security, I'm pretty sure that would get it rejected, but this is just to enable local file access. However, there's only one way to find out: submit it more app review and see what happens :-) – DaveAlden May 12 '17 at 07:15
-
6Here's the swift version: `wkWebView?.configuration.preferences.setValue(true, forKey: "allowFileAccessFromFileURLs");` – nkron May 31 '17 at 15:55
-
1Excellent tip, thanks @DaveAlden. I needed this snippet to get around a CORS issue when loading resources from a relative path with the file:/// protocol in my embedded GCDWebServer – Snouto Nov 20 '17 at 00:05
-
5i have many application using the same setting, all accepted from apple. – Mohammad Shraim Mar 28 '18 at 17:19
-
2Please comment here for any Rejection of app due to this issue. – SHS Sep 20 '18 at 10:29
-
Man this was the only solution that works for me to use three.js on iOS apps! Thanks bro!!! – Crono Oct 05 '18 at 16:44
-
1Ionic capacitor uses allowFileAccessFromFileURLs, so I guess it won't get rejected - or lots of projects will... – Nick Hingston Oct 25 '19 at 10:48
-
@DaveAlden can you please fix the link and/or quote the exact source code site? – Tomáš Hübelbauer Oct 27 '22 at 17:35
-
I also found that the code provides a setting to enable/disable the `setCrossOriginAccessControlCheckEnabled`. Can you show to set it? I posted on other question here: https://stackoverflow.com/questions/74234269/wkwebview-change-value-setcrossoriginaccesscontrolcheckenabled – Mr Hery Oct 29 '22 at 06:43
You can also add a custom URL scheme handler to the WKWebView and use that scheme in your web page. This custom scheme handler can then load data from any arbitrary location. It should be noted that this loads the entire file into memory, so it won't work for huge files.
let configuration = WKWebViewConfiguration()
configuration.setURLSchemeHandler(MySchemeHandler(), forURLScheme: "MyScheme")
let webView = WKWebView(frame: .zero, configuration: configuration)
Your MySchemeHandler needs to implement webView(_ webView: WKWebView, start urlSchemeTask: WKURLSchemeTask)
and webView(_ webView: WKWebView, stop urlSchemeTask: WKURLSchemeTask)
(although the latter can be empty). Then, convert the custom URL into a file URL and load the file.
Loading the file seems to be a pain. There might be a better way, but this is what we use:
URLSession.shared.dataTask(with: fileUrl) { data, response, error in
if error != nil {
// cancel
return
}
let taskResponse: URLResponse
if #available(iOS 13, *) {
taskResponse = HTTPURLResponse(url: urlSchemeTask.request.url!, mimeType: response?.mimeType, expectedContentLength: Int(response?.expectedContentLength ?? 0), textEncodingName: response?.textEncodingName)
} else {
// The HTTPURLResponse object created above using the URLResponse constructor crashes when sent to
// urlSchemeTask.didReceive below in iOS 12. I have no idea why that is, but it DOESN'T crash if we
// instead use the HTTPURLResponse-only constructor. Similarly, it doesn't crash if we create a
// URLResponse object instead of an HTTPURLResponse object. So, if we know the mimeType, construct an
// HTTPURLResponse using the HTTPURLResponse constructor, and add the appropriate header field for that
// mime type. If we don't know the mime type, construct a URLResponse instead.
if let mimeType = response?.mimeType {
// The imodeljs code that loads approximateTerrainHeights.json requires the HTTP Content-Type header
// to be present and accurate. URLResponse doesn't have any headers. I have no idea how the
// HTTPURLResponse contstructor could fail, but just in case it does, we fall back to the
// URLResponse object.
taskResponse = HTTPURLResponse(url: urlSchemeTask.request.url!, statusCode: 200, httpVersion: "HTTP/1.1", headerFields: ["Content-Type": "\(mimeType); charset=UTF-8"]) ?? URLResponse(url: urlSchemeTask.request.url!, mimeType: response?.mimeType, expectedContentLength: Int(response?.expectedContentLength ?? 0), textEncodingName: response?.textEncodingName)
} else {
taskResponse = URLResponse(url: urlSchemeTask.request.url!, mimeType: response?.mimeType, expectedContentLength: Int(response?.expectedContentLength ?? 0), textEncodingName: response?.textEncodingName)
}
}
urlSchemeTask.didReceive(taskResponse)
urlSchemeTask.didReceive(data!)
urlSchemeTask.didFinish()
}.resume()

- 309
- 2
- 5