You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:13:05