SwiftUI中WKWebView加载CloudFlare验证HTML显示白屏求助
iOS WKWebView加载Cloudflare验证HTML白屏问题排查
我们的链接采用CloudFlare防护,触发验证请求后后端返回HTML代码,使用WKWebView加载时iOS设备仅显示白屏。已尝试将加载逻辑从makeUIView移至updateUIView,修改了Info.plist中AllowArbitraryLoadsForWebView相关设置,均无效果。相同HTML代码在Android端可正常加载,且该HTML包含需执行的脚本,已配置相关JavaScript权限。
因隐私政策无法提供完整HTML代码,但该代码在在线工具中可正常运行。测试加载简单HTML(如<html><body><h1>Hello, World!</h1></body></html>)可正常显示。目前代理类中仅didFinish方法被调用一次,其他方法均未触发。后端返回的HTML以<!DOCTYPE html><html lang="en-US"><head><title>Just a moment....开头,以...ld(cpo);}());</script></body></html>结尾。
现有代码实现
WebView结构体
struct WebView: UIViewRepresentable { @Environment(\.dismiss) var dismiss var url: String? var html: String? var delegate: WKNavigationDelegate init(url: String) { self.url = url self.delegate = WebViewDelegate() } init(html: String, successCompletion: @escaping (DismissHandlerState) -> Void) { self.html = html self.delegate = CookieWebViewDelegate(dismissHandler: successCompletion) } }
makeUIView方法
func makeUIView(context: Context) -> WKWebView { let config = WKWebViewConfiguration() config.preferences.javaScriptCanOpenWindowsAutomatically = true config.suppressesIncrementalRendering = true let webView: WKWebView webView = WKWebView(frame: .zero, configuration: config) webView.configuration.defaultWebpagePreferences.allowsContentJavaScript = true webView.navigationDelegate = delegate webView.evaluateJavaScript("navigator.userAgent") { result, _ in if let result = result as? String { webView.customUserAgent = result CookieWebViewFeature.shared.userAgent = result } } if let url, let rawUrl = URL(string: url) { webView.load(URLRequest(url: rawUrl)) } else if let html { webView.loadHTMLString(html, baseURL: Bundle.main.bundleURL) } return webView }
代理类
final class CookieWebViewDelegate: NSObject, WKNavigationDelegate { let dismissHandler: (DismissHandlerState) -> Void init(dismissHandler: @escaping (DismissHandlerState) -> Void) { self.dismissHandler = dismissHandler } func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) { decisionHandler(.allow) } func webView(_ webView: WKWebView, didReceiveServerRedirectForProvisionalNavigation navigation: WKNavigation!) { if let url = webView.url?.absoluteString { print(url) } } func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) { print("Page Failed to load: \(error)") } func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { let dataStore = WKWebsiteDataStore.default() dataStore.httpCookieStore.getAllCookies { cookies in print(cookies) if CookieWebViewFeature.shared.checkCookie(cookies) { self.dismissHandler(.success) } else { self.dismissHandler(.failed) } } } }
排查建议
- 调整User-Agent设置时机:当前在
evaluateJavaScript回调中设置customUserAgent,但此时HTML已开始加载,Cloudflare验证可能依赖正确的UA导致逻辑执行异常。建议提前获取默认UA(例如UIDevice.current.userAgent)或构造符合要求的UA后,再加载HTML。 - 修正baseURL配置:加载HTML时使用
Bundle.main.bundleURL作为baseURL,Cloudflare验证脚本可能需要目标站点域名作为基准,导致资源加载或脚本执行失败。尝试将baseURL设置为目标站点的域名URL(如URL(string: "https://your-target-domain.com"))。 - 优化WKWebView配置:
- 显式设置
config.preferences.javaScriptEnabled = true(部分iOS版本需配合allowsContentJavaScript确保脚本权限) - 将
suppressesIncrementalRendering改为false,避免阻塞页面渲染
- 显式设置
- 排查脚本执行状态:在
didFinish方法中注入脚本,获取页面实际内容或错误信息:webView.evaluateJavaScript("document.body.innerHTML") { result, error in print("页面内容:", result ?? "无内容") print("脚本错误:", error ?? "无错误") } - 补充代理错误回调:添加
webView(_:didFailProvisionalNavigation:withError:)方法,捕获加载初期的错误信息:func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) { print("临时加载失败:", error.localizedDescription) } - 检查Cookie存储逻辑:Cloudflare验证依赖Cookie,尝试改用
WKWebsiteDataStore.nonPersistent()测试是否有旧Cookie干扰,或确保Cookie被正确存储和读取。
内容的提问来源于stack exchange,提问作者Sergey Udalov
相关产品推荐
相关产品推荐

