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

Swift:如何通过WKWebView检测用户被重定向至WiFi登录页面?

Hey,这个问题我之前在项目里也碰到过——公共WiFi那种“假连接”确实头疼,用WKWebView做通用检测的话,得结合导航监听、官方检测逻辑还有页面内容分析这几个维度,给你整理几个靠谱的方案:

通用检测Captive Portal的几种方案

1. 监听WKNavigationDelegate的自动重定向事件

WKWebView的导航代理能帮我们精准追踪页面跳转,尤其是非用户主动触发的跨域重定向,这是Captive Portal最典型的特征之一。

你可以在代理方法里记录初始请求的URL,再对比后续跳转的地址,如果域名不一致且跳转是自动触发的,基本就能判定是被认证页面拦截了:

var initialTargetURL: URL?

func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
    // 记录用户最初要加载的目标URL
    if initialTargetURL == nil {
        initialTargetURL = navigationAction.request.url
    }
    
    // 检测非主动的跨域重定向
    guard let initialURL = initialTargetURL,
          let currentURL = navigationAction.request.url,
          initialURL.host != currentURL.host,
          navigationAction.navigationType == .other else {
        decisionHandler(.allow)
        return
    }
    
    // 这里标记为疑似Captive Portal
    print("检测到自动重定向,大概率是WiFi认证页")
    decisionHandler(.allow) // 先允许加载,后续可以引导用户完成认证
}

2. 复用Apple官方的Captive Portal检测逻辑

Apple本身有一套成熟的检测机制:它会请求http://captive.apple.com/hotspot-detect.html,如果返回的内容不是预设的<HTML><HEAD><TITLE>Success</TITLE></HEAD><BODY></BODY></HTML>,就判定存在认证页面。

你可以在WKWebView加载前后,单独发起这个请求做预检测:

func checkForCaptivePortal(completion: @escaping (Bool) -> Void) {
    guard let detectURL = URL(string: "http://captive.apple.com/hotspot-detect.html") else {
        completion(false)
        return
    }
    
    let task = URLSession.shared.dataTask(with: detectURL) { data, _, error in
        guard let data = data,
              let responseHTML = String(data: data, encoding: .utf8) else {
            completion(false)
            return
        }
        
        // 对比是否是Apple预期的成功响应
        let isCaptive = !responseHTML.contains("<TITLE>Success</TITLE>")
        completion(isCaptive)
    }
    task.resume()
}

// 在WKWebView加载前调用预检测
checkForCaptivePortal { isCaptive in
    if isCaptive {
        print("存在WiFi认证页,请引导用户完成认证")
        // 可以直接让WKWebView加载这个检测地址,会自动跳转到认证页面
    }
}

3. 结合页面内容特征做二次验证

有些Captive Portal不会直接跨域重定向,而是在原域名下返回认证内容。这种情况可以通过检测页面的标题、文本关键词来判断:

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
    // 注入JS获取页面标题和内容
    webView.evaluateJavaScript("document.title + '||' + document.body.innerText") { result, _ in
        guard let contentStr = result as? String else { return }
        let contentParts = contentStr.split(separator: "||")
        let pageTitle = contentParts.first ?? ""
        let pageBody = contentParts.last ?? ""
        
        // 检测常见的认证关键词(多语言适配可以扩展)
        let captiveKeywords = ["登录", "认证", "WiFi", "Hotspot", "Sign In", "Authenticate"]
        let hasCaptiveFlag = captiveKeywords.contains { 
            pageTitle.contains($0) || pageBody.contains($0) 
        }
        
        if hasCaptiveFlag {
            print("当前页面是WiFi认证页")
        }
    }
}

额外注意事项

  • 优先用HTTP请求做检测:大部分Captive Portal会拦截HTTP请求进行重定向,HTTPS请求可能直接失败,不会跳转到认证页
  • 区分主动跳转和自动重定向:避免把用户主动点击的跨域链接误判为认证页
  • 组合多种方案:比如先做Apple官方检测,再监听重定向,最后检查页面内容,能大幅提升检测准确率

内容的提问来源于stack exchange,提问作者FranticRock

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:34:59