2017-02-06 4 views
2

Ich versuche, einige Daten zu senden, die der Benutzer in einer mysql-Datenbank auf einem LAMP-Server auswählt, der sich in einem anderen Netzwerk befindet. Kürzlich habe ich einen Server auf meine eigene Maschine heruntergeladen und alles war in Ordnung. Die Aktion in der App wurde an die php-Datei gesendet, die sich auf dem Server befand, und dann hat natürlich der php das Senden an die mysql-Datenbank erledigt. Kürzlich erhielt ich Zugang zu einem Server, den wir benutzen müssen. Wenn ich nun das gleiche versuche, bekomme ich eine Fehlermeldung, dass das Zertifikat für diesen Server ungültig ist. Ich weiß, dass ich vorher mit http beschäftigt habe und jetzt muss es https sein, aber ich bin nicht klar darüber, wie ich das ändern sollte, damit es richtig funktioniert. Ich sehe hier viele verschiedene Antworten darauf, wie dies zu tun ist, aber sie werden oft mit Kommentaren wie "Dies ist ein Workaround" oder "Die App könnte abgelehnt werden" und so weiter konterkariert.Senden einer Postanforderung mit swift 3 (selbstsigniertes Zertifikat)

Hier ist meine aktuelle Funktion:

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

}

Ich lese Dinge wie hier nicht geteilt mit, um es zu arbeiten, aber ich bin immer noch nicht ganz klar zu diesem Thema. Alles, was ich tun möchte, ist diese Daten an ein PHP auf dem Server zu senden. Die Daten selbst sind nicht sensitiv, es werden nur Geschlecht und Ja oder Nein-Antworten an eine Datenbank gesendet. Allerdings müsste dies sicher genug sein, wenn keine Angriffe die Benutzererfahrung beeinträchtigen und aus diesem Grund nicht zurückgewiesen werden. Jede Hilfe hier würde sehr geschätzt werden. Dank

Antwort

4

Sie müssen zwei Dinge tun:

  1. die Domain Ausnahme Ihre plist-Datei hinzufügen, ich Sie auf diese beziehen How do I load an HTTP URL with App Transport Security enabled in iOS 9?

  2. Sie benötigen Stackoverflow Posten Sie Ihre URLSessionDelegate zu implementieren. Diese eine Methode ist das absolute Minimum für Ihre https-Anfrage. Sie finden eine fast exakte Methode für URLSessionTaskDelegate, diese Methode ist für die aufgabenspezifische Authentifizierung, diese ist für session-weite Authentifizierung. Wie Sie aus dem Code entnehmen können, ist der entscheidende Teil URLCredential (trust: challenge.protectionSpace.serverTrust!), Wo Sie angeben, dass Sie diesem Server vertrauen.

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

    }

Dann machen Sie einfach die URLSession(configuration: URLSessionConfiguration.default, delegate: RequestDelegate(), delegateQueue: nil) mit Delegierten als Argument

Getestet und funktioniert auf IOS 10.

this helps , das ist eigentlich mein erstes Post auf stackoverflow, also Hallo Welt.

+0

ist es möglich, ein bisschen mehr bitte zu erarbeiten. – nyxee

+0

@nyxee wo bist du stecken geblieben? – blackcat

+0

posted meine volle Funktion unter .. – nyxee

1

Ich habe all dies (die so genannte SSL-Pinning) ...

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

wird wenn nötig, mehr erklären. Die Funktion soll in der Klasse mit der URLSession sein. Die Klasse sollte URLSessionDelegate erweitern.

Verwandte Themen