Ios 使用swift 3发送post请求(自签名证书颁发)

Ios 使用swift 3发送post请求(自签名证书颁发),ios,swift3,Ios,Swift3,我试图将用户将选择的一些数据发送到位于不同网络上的LAMP服务器上的mysql数据库。最近我在自己的机器上下载了一个服务器,一切都很好。应用程序中的操作发送到服务器中的php文件,然后php处理将其发送到mysql数据库。最近我被允许访问一个我们需要使用的服务器。现在,当我尝试做同样的事情时,我得到一个错误,说这个服务器的证书无效。我知道以前我处理的是http,现在它需要是https,但我不清楚应该如何更改它以使其正常工作。我在这里看到了很多关于如何做到这一点的不同回应,但他们经常被诸如“这是一

我试图将用户将选择的一些数据发送到位于不同网络上的LAMP服务器上的mysql数据库。最近我在自己的机器上下载了一个服务器,一切都很好。应用程序中的操作发送到服务器中的php文件,然后php处理将其发送到mysql数据库。最近我被允许访问一个我们需要使用的服务器。现在,当我尝试做同样的事情时,我得到一个错误,说这个服务器的证书无效。我知道以前我处理的是http,现在它需要是https,但我不清楚应该如何更改它以使其正常工作。我在这里看到了很多关于如何做到这一点的不同回应,但他们经常被诸如“这是一个解决办法”或“应用程序可能被拒绝”等评论所反驳

以下是我目前的职能:

func sendToServer(firstEntry: String, secondEntry: String, serverAddr: String){

let uid = firstEntry
let gender = secondEntry
let request = NSMutableURLRequest(url: NSURL(string: serverAddr)! as URL)
request.httpMethod = "POST"
let postString = "UID=\(uid)&Gender=\(gender)"
request.httpBody = postString.data(using: String.Encoding.utf8)

let task = URLSession.shared.dataTask(with: request as URLRequest) {
    data, response, error in

    if error != nil {
        print("error=\(error)")
        return
    }

    print("response = \(response)")

    let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
    print("responseString = \(responseString)")
}
task.resume()
}


我读过一些东西,比如不使用sharedhere来让它工作,但我仍然不太清楚这一点。我只想将这些数据发送到服务器上的php。数据本身并不敏感,只是性别和是或否的答案被发送到数据库。但是,在没有影响用户体验的攻击以及不会因此被拒绝的情况下,我需要足够的安全性。这里的任何帮助都将不胜感激。谢谢

您需要做两件事:

  • 将域异常添加到您的plist文件中,我将向您推荐此stackoverflow帖子

  • 您需要实现URLSessionLegate。此方法是https请求的最低要求。您将在URLSessionTaskDelegate上找到一个几乎完全相同的方法,该方法用于特定于任务的身份验证,该方法用于会话范围的身份验证。正如您从代码中看到的,关键部分是URLCredential(信任:challenge.protectionSpace.serverTrust!),您可以在其中指定信任该服务器

  • 然后,您只需使用委托作为参数来创建
    URLSession(配置:URLSessionConfiguration.default,委托:RequestDelegate(),delegateQueue:nil)

    在IOS 10上测试和工作

    希望这有帮助,这实际上是我第一篇关于stackoverflow的文章,所以大家好。我有所有这些(称为SSL固定)

    如有必要,我们将进一步解释。
    该函数应该位于具有URLSession的类中。该类应扩展URLSessionDelegate。

    缺少self.isSimulatingCertificateCorruption实现

    请再详细说明一下好吗?@nyxee你在哪里被卡住了?
        class RequestDelegate: NSObject, URLSessionDelegate {
    
            public func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Swift.Void) {
                completionHandler(URLSession.AuthChallengeDisposition.useCredential, URLCredential(trust: challenge.protectionSpace.serverTrust!))
            }
        }
    
    // MARK: URL session delegate
    func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
        //Implementation 1: VERY WEAK METHOD
        /*if challenge.previousFailureCount > 0{
         completionHandler(URLSession.AuthChallengeDisposition.cancelAuthenticationChallenge, nil)
         }else{
         completionHandler(URLSession.AuthChallengeDisposition.useCredential, URLCredential(trust:challenge.protectionSpace.serverTrust!))
         }*/
    
        //Implementation 2:
        var disposition: URLSession.AuthChallengeDisposition = URLSession.AuthChallengeDisposition.performDefaultHandling
        var credential:URLCredential?
    
        if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
            //certificate-based server credentials are used when verifying the server’s identity
            credential = URLCredential(trust: challenge.protectionSpace.serverTrust!)
    
            if (credential != nil) {
                disposition = URLSession.AuthChallengeDisposition.useCredential
            }
            else{
                disposition = URLSession.AuthChallengeDisposition.performDefaultHandling
            }
        }
        else{
            disposition = URLSession.AuthChallengeDisposition.cancelAuthenticationChallenge
        }
        print("==============",#file.getClass()," ", #function,"  disposition: ", disposition)
        print("==============",#file.getClass()," ", #function,"  disposition: ", credential!)
    
        //completionHandler(disposition, credential);
    
    
    
    
        //Implementation 3:
        let serverTrust = challenge.protectionSpace.serverTrust
        let certificate = SecTrustGetCertificateAtIndex(serverTrust!, 0)
    
        // Set SSL policies for domain name check
        let policies = NSMutableArray();
        policies.add(SecPolicyCreateSSL(true, (challenge.protectionSpace.host as CFString)))
        SecTrustSetPolicies(serverTrust!, policies);
    
        // Evaluate server certificate
        var result = SecTrustResultType(rawValue: 0)!
        SecTrustEvaluate(serverTrust!, &result)
    
        let isServerTrusted:Bool = (result == SecTrustResultType.unspecified || result == SecTrustResultType.unspecified || result == SecTrustResultType.proceed)
        print("==============",#file.getClass()," ", #function,"  isServerTrusted: ", isServerTrusted)
        print("==============",#file.getClass()," ", #function,"  result: ", result.hashValue,"  SecTrustResultType.unspecified: ", SecTrustResultType.unspecified.hashValue,"  SecTrustResultType.proceed: ", SecTrustResultType.proceed.hashValue)
        var certName = ""
        if self.isSimulatingCertificateCorruption {
            certName = corruptedCert
        } else {
            certName = cert
        }
    
        // Get local and remote cert data
        let remoteCertificateData = SecCertificateCopyData(certificate!) as Data
        let pathToCert            = Bundle.main.path(forResource: certName, ofType: "der")
        let localCertificate      = try! Data(contentsOf: URL(fileURLWithPath: pathToCert!))
        print(" remoteCertificateData: ", remoteCertificateData,"       localCertificate: ", localCertificate, "       serverTrust: ", serverTrust.debugDescription  )
    
        if ( remoteCertificateData == localCertificate) { //TODO:- this is strictly for tesing puposes, to allow untrusted severs. REMOVE IN PRODUCTION.
            let credential:URLCredential = URLCredential(trust: serverTrust!)
            completionHandler(.useCredential, credential)
        }else if (isServerTrusted && (remoteCertificateData == localCertificate)) {
            let credential:URLCredential = URLCredential(trust: serverTrust!)
            completionHandler(.useCredential, credential)
        } else {
            completionHandler(.cancelAuthenticationChallenge, nil)
        }
    }