iOS Swift中从WKWebView获取登录生成Token的完整方案咨询
完整解决方案:从WKWebView获取登录后的Token
嘿,我来帮你搞定这个WKWebView获取Token的问题!你现在的代码已经搭好了登录页加载的基础,接下来分两种最常用的场景给你完整方案,你可以根据实际情况选择:
场景1:Token在跳转URL的参数中(比如跳转到带参数的自定义Scheme或HTTP地址)
这种情况是网页登录成功后,会跳转到一个包含Token参数的地址,我们可以通过WKWebView的代理拦截这个跳转,提取出Token。
步骤1:设置WKWebView的代理
首先,让你的ViewController遵循WKNavigationDelegate协议,然后给webView设置代理:
class YourViewController: UIViewController, WKNavigationDelegate { var webView: WKWebView! override func loadView() { super.loadView() // 替换成你的实际登录URL guard let url = URL(string: "https://your-login-page.com") else { fatalError("Invalid login URL") } let request = URLRequest(url: url) let config = WKWebViewConfiguration() webView = WKWebView(frame: self.view.bounds, configuration: config) // 关键:设置导航代理 webView.navigationDelegate = self webView.load(request) self.view.addSubview(webView!) } }
步骤2:拦截跳转并提取Token
实现WKNavigationDelegate的webView(_:decidePolicyFor:decisionHandler:)方法,在这里检查跳转的URL,提取Token:
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { guard let targetURL = navigationAction.request.url else { decisionHandler(.allow) return } // 情况A:网页跳转到自定义Scheme(比如你定义的`yourapp://get-token?token=xxx`) if targetURL.scheme == "yourapp" { // 提取Token参数 if let token = targetURL.queryParameters?["token"] { // 搞定!拿到Token了,这里可以做后续处理:比如存到Keychain、跳转到首页等 print("获取到Token:\(token)") // 示例:关闭当前WebView页面 // self.dismiss(animated: true) } // 阻止WebView跳转这个自定义Scheme(因为我们已经处理了) decisionHandler(.cancel) return } // 情况B:网页跳转到HTTP/HTTPS页面,Token在URL参数里(比如`https://your-app.com/token-callback?value=xxx`) if targetURL.host == "your-app.com" && targetURL.path == "/token-callback" { if let token = targetURL.queryParameters?["value"] { print("获取到Token:\(token)") // 处理Token逻辑 } // 根据需求选择允许或阻止跳转,这里建议阻止避免多余页面加载 decisionHandler(.cancel) return } // 其他正常的页面跳转,允许通过 decisionHandler(.allow) }
小工具:URL参数解析扩展
为了方便提取URL里的参数,给URL加个实用扩展:
extension URL { var queryParameters: [String: String]? { guard let components = URLComponents(url: self, resolvingAgainstBaseURL: true), let queryItems = components.queryItems else { return nil } return queryItems.reduce(into: [String: String]()) { result, item in result[item.name] = item.value } } }
场景2:网页通过JS主动调用原生方法传Token(适合你能控制网页代码的情况)
如果登录后的网页是你们团队开发的,这种方式更可靠——让前端在拿到Token后,直接调用原生Swift的方法把Token传过来。
步骤1:配置WKWebView的JS交互
在初始化WKWebView的时候,添加一个WKUserContentController,注册一个消息处理器:
override func loadView() { super.loadView() guard let url = URL(string: "https://your-login-page.com") else { fatalError("Invalid login URL") } let request = URLRequest(url: url) // 创建用户内容控制器,用于JS和原生交互 let userContentController = WKUserContentController() // 注册一个名为"sendTokenToNative"的消息处理器,前端JS会通过这个名字调用 userContentController.add(self, name: "sendTokenToNative") let config = WKWebViewConfiguration() config.userContentController = userContentController webView = WKWebView(frame: self.view.bounds, configuration: config) webView.navigationDelegate = self webView.load(request) self.view.addSubview(webView!) }
步骤2:实现JS消息接收协议
让你的ViewController遵循WKScriptMessageHandler协议,实现接收JS消息的方法:
extension YourViewController: WKScriptMessageHandler { func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { // 检查消息名称是否匹配我们注册的 if message.name == "sendTokenToNative" { // 从message.body中获取Token,这里假设前端传的是字符串,也可能是字典,根据实际情况调整 if let token = message.body as? String { print("从JS获取到Token:\(token)") // 后续处理:存安全存储、跳转页面等 } } } }
步骤3:前端对应的JS代码
让前端同事在拿到Token后,执行这段JS代码:
// 假设token是前端拿到的令牌字符串 window.webkit.messageHandlers.sendTokenToNative.postMessage(token);
重要注意事项
- 安全存储Token:别用
UserDefaults存Token,建议用Keychain,因为Keychain是系统级的安全存储,适合存敏感信息。 - 自定义Scheme配置:如果用场景1的自定义Scheme,需要在Info.plist中添加
LSApplicationQueriesSchemes数组,把你的Scheme(比如yourapp)加进去,否则iOS会拦截跳转。 - 避免内存泄漏:在ViewController销毁时,记得移除JS消息处理器:
deinit { webView?.configuration.userContentController.removeScriptMessageHandler(forName: "sendTokenToNative") }
内容的提问来源于stack exchange,提问作者Vaisakh Mohan
相关产品推荐
相关产品推荐

