【问题标题】:Install TLS certificates on web server iOS app在 Web 服务器 iOS 应用上安装 TLS 证书
【发布时间】:2019-05-21 22:53:39
【问题描述】:

我正在尝试将 Swish 支付集成到我开发的一款应用中。 为了能够连接到 swish api,我必须根据文档“从 Swish 证书管理设置 TLS 证书并将其安装在“我的”网络服务器上”。这是完整的技术文档https://developer.getswish.se/merchants-api-manual/4-merchant-setup-process/

我不明白的问题是我没有使用网络服务器,也无法在那里安装这些证书。

我的应用只是为客户提供一些服务,按下支付按钮后应该会打开 Swish 应用以完成交易。

我尝试的是发出一个发布请求以获取请求令牌,我可以使用它打开加载了付款详细信息的 swish 应用程序。 我确定问题出在证书上,但找不到解释如何导入(集成)它们的好来源。

让 strURL = "https://mss.cpc.getswish.net/swish-cpcapi/api/v1/paymentrequests/"

guard let postURL = URL(string: strURL) else { print("无法创建网址") 返回 }

    var request = URLRequest(url: postURL)

    request.httpMethod = "POST"
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    request.setValue("application/json", forHTTPHeaderField: "Accept")

    let data: [String: Any] = [
        "callbackUrl": "https://example.com/api/swishcb/paymentrequests",
        "payeeAlias": "123xxxxxxx", // The Swish number of the payee. It needs to match with Merchant Swish number.
        "amount": "100",
        "currency": "SEK",
        "message": "Test request to get the token"
    ]

    do {
        let jsonParams = try JSONSerialization.data(withJSONObject: data, options: [])
        request.httpBody = jsonParams
    } catch {
        print("Error serializing the parameters of the post request")
        return
    }

    // response will contain a Token, unique for each payment request

    let config = URLSessionConfiguration.default
    config.timeoutIntervalForResource = 120
    config.timeoutIntervalForRequest = 120
    let session = URLSession(configuration: config) 

    session.dataTask(with: request) { (data, response, error) in
        print("Data \(data)")
        print("Response \(response)")
        if error != nil {
            print("Error post request \(error?.localizedDescription)")
        }
    }.resume()

我得到的错误是: 错误发布请求可选(“发生 SSL 错误,无法与服务器建立安全连接。”)

018-12-21 12:24:55.549759+0200 tolk-24-7[7230:111102] [BoringSSL]boringssl_context_alert_callback_handler(3718) [C6.1:2][0x7fce4a77bf00] 警报级别:致命,描述:握手失败 2018-12-21 12:24:55.550047+0200 tolk-24-7[7230:111102] [BoringSSL]boringssl_session_errorlog(224) [C6.1:2][0x7fce4a77bf00] [boringssl_session_handshake_incomplete] SSL_ERROR_SSL(1):内部操作失败图书馆 2018-12-21 12:24:55.550332+0200 tolk-24-7[7230:111102] [BoringSSL]boringssl_session_handshake_error_print(205) [C6.1:2][0x7fce4a77bf00] 140523985879704:error:10000410:OPSSL 例程_internal:SSL:EN: SSLV3_ALERT_HANDSHAKE_FAILURE:/BuildRoot/Library/Caches/com.apple.xbs/Sources/boringssl_Sim/boringssl-109.220.4/ssl/tls_record.cc:586:SSL 警报编号 40 2018-12-21 12:24:55.550585+0200 tolk-24-7[7230:111102] [BoringSSL]boringssl_context_get_error_code(3539) [C6.1:2][0x7fce4a77bf00] SSL_AD_HANDSHAKE_FAILURE 2018-12-21 12:24:55.552299+0200 tolk-24-7[7230:111102] TI​​C TCP 连接失败 [6:0x600002dd6c40]: 3:-9824 Err(-9824) 2018-12-21 12:24:55.555924+0200 tolk-24-7[7230:111102] NSURLSession/NSURLConnection HTTP 加载失败(kCFStreamErrorDomainSSL,-9824) 2018-12-21 12:24:55.556052+0200 tolk-24-7[7230:111102] 任务 . HTTP 加载失败(错误代码:-1200 [3: -9824]) 2018-12-21 12:24:55.556234+0200 tolk-24-7[7230:111613] 任务 . 完成错误 - 代码:-1200

【问题讨论】:

    标签: swift swish


    【解决方案1】:

    我感到你很沮丧,我没有使用 Swish API 本身,但看起来 URLSession 无法执行客户端证书请求。握手在该步骤失败。

    有一个选项可以将 URLSessionDelegate 添加到 URLSession 以处理身份验证挑战,例如 ServerTrust 和 ClientCertificate。他们在这里讨论它: Swift 3 UrlSession with client authentication by certificate

    如果您能够使用客户端证书和私钥创建 p12/pfx,则可以使用 SecPKCS12Import 将其导入,并将其用于 URLSessionDelegate 中收到的 NSURLAuthenticationMethodClientCertificate 中的 URLCredential 信任。这是我写的一个实现:

    func urlSession(
            _ session: URLSession,
            didReceive challenge: URLAuthenticationChallenge,
            completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)
        {
    
            let authenticationMethod = challenge.protectionSpace.authenticationMethod
            if authenticationMethod == NSURLAuthenticationMethodServerTrust {
                //Handle server trust if necessary
            } else if authenticationMethod == NSURLAuthenticationMethodClientCertificate {
                if let clientCredential = try? getClientUrlCredential() {
                    completionHandler(.useCredential, clientCredential)
                } else {
                    completionHandler(.cancelAuthenticationChallenge, nil)
                }
            }
        }
    

    getClientUrlCredential 函数:

    private func getClientUrlCredential() throws -> URLCredential {
    
            let p12Data = getP12Data() //Get the data from the bundle if it's bundled in the app
            let p12Key = getP12Key() //you need the key set for creating the p12/pfx
    
            let certOptions: NSDictionary = [
                kSecImportExportPassphrase as NSString : p12Key as NSString
            ]
    
            // import certificate to read its entries
            var items: CFArray?
            let status = SecPKCS12Import(p12Data, certOptions, &items)
    
            if status == errSecSuccess,
                let items = items,
                let dict = (items as Array).first as? [String: AnyObject],
                let certChain = dict[kSecImportItemCertChain as String] as? [SecTrust] {
    
                // Check if SecIdentityGetTypeID is present
                guard let cfIdentity = dict[kSecImportItemIdentity as String] as CFTypeRef?,
                    CFGetTypeID(cfIdentity) == SecIdentityGetTypeID() else {
                        throw URLSessionPinningDelegateError.localClientCertificateError
                }
    
                let identity = dict[kSecImportItemIdentity as String] as! SecIdentity
                return URLCredential(
                    identity: identity,
                    certificates: certChain,
                    persistence: .forSession
                )
            }
    
            //Failed to read local certificate, throw error
            throw URLSessionPinningDelegateError.localClientCertificateError
        }
    

    使用有效的客户端证书,您应该能够完成客户端问候并设置针对服务器的 TLS,因为这似乎是您现在失败的地方。 BoringSSL 收到的 SSL 警报编号 40 至少对我来说是这样的。

    希望这至少可以为您指明正确的方向,如果需要,我们很乐意提供进一步的支持。

    【讨论】:

      猜你喜欢
      • 2016-04-16
      • 2016-06-17
      • 2016-10-20
      • 2013-02-25
      • 2012-11-04
      • 2020-06-08
      • 2021-11-11
      • 2014-02-12
      • 2016-06-15
      相关资源
      最近更新 更多