You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何捕获App Transport Security错误?NSURLSession ATS报错监听方法咨询

捕获App Transport Security(ATS)错误及NSURLSession相关处理机制

嘿,我来帮你理清ATS错误捕获和NSURLSession的相关处理方式,这在iOS开发中是个常见的问题:

一、如何捕获ATS错误

ATS的错误本质上属于NSURLErrorDomain下的网络错误,最典型的就是错误码NSURLErrorAppTransportSecurityRequiresSecureConnection(对应数值-1022),它会在你尝试用HTTP而非HTTPS请求,或者连接的HTTPS不符合ATS安全标准时触发。

你可以通过两种核心方式捕获这些错误:

  • Completion Handler 直接捕获:如果用的是URLSession.shared的便捷方法,在completion block里就能拿到错误对象。举个例子:
let insecureURL = URL(string: "http://non-https-site.com")!
let task = URLSession.shared.dataTask(with: insecureURL) { data, response, error in
    guard let error = error as NSError? else {
        // 请求成功,处理数据
        return
    }
    
    if error.domain == NSURLErrorDomain && error.code == NSURLErrorAppTransportSecurityRequiresSecureConnection {
        print("ATS拦截了请求:需要使用安全的HTTPS连接")
        // 这里可以做用户提示、日志记录或者跳转HTTPS地址
    }
}
task.resume()
  • 代理方法捕获:如果你用了自定义的URLSession并设置了代理,代理回调会更灵活,这部分我下面详细说。

二、NSURLSession接收ATS错误的代理机制

当URL不符合ATS规范导致dataTask被终止时,确实有专门的代理方法能接收错误通知,主要有这两个:

1. URLSession:task:didCompleteWithError:

这是最通用的任务完成回调,不管任务成功还是失败都会触发。ATS错误发生时,error参数会完整携带错误信息。用法如下:
首先要让你的类遵守URLSessionTaskDelegate协议,然后实现代理方法:

extension YourViewController: URLSessionTaskDelegate {
    func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
        guard let error = error as NSError? else {
            print("任务完成,无错误")
            return
        }
        
        if error.domain == NSURLErrorDomain && error.code == NSURLErrorAppTransportSecurityRequiresSecureConnection {
            print("ATS错误触发:\(error.localizedDescription)")
            // 这里可以加入自定义逻辑,比如弹出提示框告知用户连接不安全
        }
    }
}

注意:要使用这个代理,你需要初始化自定义URLSession时指定代理和队列:

let config = URLSessionConfiguration.default
let session = URLSession(configuration: config, delegate: self, delegateQueue: OperationQueue.main)

2. URLSession:didReceiveChallenge:completionHandler:(针对证书类ATS错误)

如果ATS错误是因为服务器证书不被信任(比如自签名证书、证书过期),这个代理方法会被调用。它主要用于处理身份验证挑战,虽然不是单纯的HTTP转HTTPS错误,但也是ATS相关的场景。示例代码:

extension YourViewController: URLSessionDelegate {
    func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
        // 仅处理服务器信任验证的情况
        if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
            // 注意:正式环境不建议随便绕过证书验证,这会降低安全性
            let credential = URLCredential(trust: challenge.protectionSpace.serverTrust!)
            completionHandler(.useCredential, credential)
        } else {
            // 其他类型的挑战,交给系统默认处理
            completionHandler(.performDefaultHandling, nil)
        }
    }
}

额外小提示

  • 优先通过错误码判断ATS错误,localizedDescription虽然友好,但会随系统语言变化,不够稳定。
  • 测试阶段如果需要临时绕过ATS,可以在Info.plist里添加NSAppTransportSecurity字典,设置NSAllowsArbitraryLoadsYES,但上线前一定要移除这个设置,苹果对非合规ATS配置的审核非常严格。

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

火山引擎 最新活动