Alamofire 请求失败,因为证书但在 Postman 上工作

Posted

技术标签:

【中文标题】Alamofire 请求失败,因为证书但在 Postman 上工作【英文标题】:Alamofire fail request because certificate but work on Postman 【发布时间】:2020-11-23 00:13:41 【问题描述】:

我正在处理的一个请求有问题。

使用邮递员,此请求适用于一个警告“证书链中的自签名证书”

如果你想试试,这里是卷曲:

curl --location --request GET 'https://app-server.iot.i.tplinknbu.com/v1/server-info' \
--header 'Content-Type: application/json' \
--header 'app-cid: app:TP-Link_Tapo_android:98-3B-16-96-48-EB' \
--data-raw ''

但使用 Almofire 或 ios 的默认请求系统会失败:

2020-11-22 23:47:50.192188+0000 App [4483:1574605] Task <E6235AC9-2246-4F32-BB17-CB969F244030>.<2> HTTP load failed, 0/0 bytes (error code: -1200 [3:-9802])
2020-11-22 23:47:50.195117+0000 App[4483:1574592] Task <E6235AC9-2246-4F32-BB17-CB969F244030>.<2> finished with error [-1200] Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo=NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, NSErrorPeerCertificateChainKey=(
    "<cert(0x151093800) s: *.tplinknbu.com i: TP-LINK CA P1>",
    "<cert(0x151094000) s: TP-LINK CA P1 i: tp-link-CA>",
    "<cert(0x15106e200) s: tp-link-CA i: tp-link-CA>"
), NSErrorClientCertificateStateKey=0, NSErrorFailingURLKey=https://app-server.iot.i.tplinknbu.com/v1/server-info, NSErrorFailingURLStringKey=https://app-server.iot.i.tplinknbu.com/v1/server-info, NSUnderlyingError=0x282b23e10 Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)" UserInfo=_kCFStreamPropertySSLClientCertificateState=0, kCFStreamPropertySSLPeerTrust=<SecTrustRef: 0x281760f30>, _kCFNetworkCFStreamSSLErrorOriginalValue=-9802, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9802, kCFStreamPropertySSLPeerCertificates=(
    "<cert(0x151093800) s: *.tplinknbu.com i: TP-LINK CA P1>",
    "<cert(0x151094000) s: TP-LINK CA P1 i: tp-link-CA>",
    "<cert(0x15106e200) s: tp-link-CA i: tp-link-CA>"
), _NSURLErrorRelatedURLSessionTaskErrorKey=(
    "LocalDataTask <E6235AC9-2246-4F32-BB17-CB969F244030>.<2>"
), _kCFStreamErrorCodeKey=-9802, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <E6235AC9-2246-4F32-BB17-CB969F244030>.<2>, NSURLErrorFailingURLPeerTrustErrorKey=<SecTrustRef: 0x281760f30>, NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made.

这是我正在使用的代码:

info.plist:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
    <key>NSExceptionMinimumTLSVersion</key>
    <string>TLSv1.2</string>
    <key>NSThirdPartyExceptionMinimumTLSVersion</key>
    <string>TLSv1.2</string>
    <key>NSAllowsLocalNetworking</key>
    <true/>
</dict>

代码:

let defaultManager: ServerTrustManager = 
    let serverTrustPolicies: [String: ServerTrustEvaluating] = [
        "tplinknbu.com": DisabledTrustEvaluator(),
        "tplinknbu.com:443": DisabledTrustEvaluator()
    ]

    return Alamofire.ServerTrustManager(evaluators: serverTrustPolicies)
()

    let pathURL = URL(string: "https://app-server.iot.i.tplinknbu.com/v1/server-info")
    var request = URLRequest(url: pathURL!)
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    request.httpMethod = HTTPMethod.get.rawValue
    
    
    let dataRequest = Session(serverTrustManager: defaultManager, eventMonitors: [AlamofireLogger()]).request(request).responseJSON 
        (response) in
        
        
        switch response.result 
        case .failure(let error):
            
            print(error)
        default: break

        
    

我做错了什么?

附:如果我使用代理工具 Proxyman 并激活他们在 iPhone 上拥有的 Proxyman 证书,那么在 iOS 应用程序上一切正常

【问题讨论】:

您的会话对象可能是问题所在,它在处理请求之前进行了戴尔分配,尝试将其分配给函数之外的变量,然后检查,有同样的问题。 @ShivamGaur 谢谢你,你说得对,我输了!!! 【参考方案1】:

您必须与您正在使用的主机完全匹配。那就是tplinknbu.com 不匹配app-server.iot.i.tplinknbu.com。您还应该直接调查您看到的错误,因为它们可能包含有用的信息。

就像@Shivam Gaur 所说,您不应该像这样内联创建Session 实例。您需要在类似单例的情况下保持它们的引用有效,以便请求可以完成。

【讨论】:

owww 我没有意识到它必须是完整的 URL。所以修复是 + 存储会话 + plist 只是设置为 NSAllowsArbitraryLoads

以上是关于Alamofire 请求失败,因为证书但在 Postman 上工作的主要内容,如果未能解决你的问题,请参考以下文章

Alamofire 请求最初返回值,但在通过完成处理程序时被接收为 nil

Alamofire HTTP 请求失败

为啥请求 Alamofire 失败?

使用 Alamofire 2.0 请求失败

401 alamofire 获取带有标头的请求

请求失败时从 AlamoFire 获取 JSON 响应