2017-02-06 32 views
2

我想發送一些數據,用戶將選擇到一個不同的網絡上的LAMP服務器上的MySQL數據庫。最近我在自己的機器上下載了一臺服務器,一切都很好。應用程序中的動作發送到服務器中的php文件,然後當然將php發送到mysql數據庫。最近我被授予訪問我們需要使用的服務器的權限。現在,當我嘗試做同樣的事情時,我得到一個錯誤,說這個服務器的證書是無效的。我知道以前我在處理http,現在它需要是https,但我不清楚我應該如何改變它以使其正常工作。我在這裏看到了很多關於如何做到這一點的不同反應,但他們常常被諸如「這是一種解決方法」或「該應用可能被拒絕」等評論反駁。發送郵件請求與迅速3(自簽名證書問題)

這裏是我當前的功能:

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() 

}

我讀的東西,如不使用此共享才能正常工作,但我現在還不能對這個很清楚。我想要做的就是將這些數據發送到位於服務器上的php。數據本身並不敏感,它只是簡單地將性別,是或否發送到數據庫的答案。但是,如果沒有影響用戶體驗的攻擊以及不會因此而拒絕的攻擊,我需要足夠安全。任何幫助在這裏將不勝感激。由於

回答

4

你需要做兩件事情:

  1. 添加域例外的plist文件,我會向您推薦這個StackOverflow的發佈How do I load an HTTP URL with App Transport Security enabled in iOS 9?

  2. 你需要實現你的URLSessionDelegate。這一個方法對於你的https請求來說是最小的。您將在URLSessionTaskDelegate上找到一個幾乎精確的方法,該方法用於特定於任務的身份驗證,此方法用於會話範圍身份驗證。從代碼中可以看到,關鍵部分是URLCredential(trust:challenge.protectionSpace.serverTrust!),您可以在其中指定您信任該服務器。

    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!)) 
    } 
    

    }

然後你只需讓URLSession(configuration: URLSessionConfiguration.default, delegate: RequestDelegate(), delegateQueue: nil)與委派作爲參數

測試和IOS 10.工作

希望這有助於,這實際上是我的第一個發佈在stackoverflow上,所以Hello World。

+0

是否可以詳細說明一下。 – nyxee

+0

@nyxee你卡在哪裏? – blackcat

+0

在下面發佈了我的全部功能.. – nyxee

1

我都這樣(被稱爲SSL鋼釘)...

// 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) 
    } 
} 

將解釋更多,如果必要的。 該函數應該在URLSession類中。該類應該擴展URLSessionDelegate。