2017-10-13 106 views
1

嗨iam試圖從HTTPS網址獲取請求。但Iam不斷得到錯誤。Swift 3 HTTPS GET請求

2017-10-13 18:13:43.372427+0800 VQ Smart Home[13412:2155414] Unknown class _TtC13VQ_Smart_Home16ManageUserstable in Interface 

Builder文件。 VQ Smart Home [13412:2155471] TQ SSL信任錯誤[6:0x604000167680]:3:0 2017-10-13 18:13:43.403672 + 0800 VQ Smart Home [13412:2155471] NSURLSession/NSURLConnection的HTTP加載失敗 (kCFStreamErrorDomainSSL,-9813) 2017年10月13日18:13:43.404000 + 0800 VQ智能家居[13412:2155471]任務< 8BB05664-B56E-41CA-92F7-BBAECC8008E3 >。 < 5> HTTP加載失敗(錯誤 代碼:-1202 [3:-9813]) 2017-10-13 18:13:43.404496 + 0800 VQ智能家居[13412:2155472]任務< 8BB05664-B56E-41CA-92F7 -BBAECC8008E3>。 < 5>用錯誤代碼: -1202 錯誤=可選(錯誤域= NSURLErrorDomain代碼= -1202「此服務器的證書無效。您可能正在連接到假裝爲」202.73「的 服務器。 46.176」 ,這可能會危害您的 機密信息。」 的UserInfo = {NSURLErrorFailingURLPeerTrustErrorKey =,= NSLocalizedRecoverySuggestion你想 連接到服務器嗎?_kCFStreamErrorDomainKey = 3, _kCFStreamErrorCodeKey = -9813,NSErrorPeerCertificateChainKey =( 「」 ),NSUnderlyingError = 0x60400025c920 {Error Domain = kCFErrorDomainCFNetwork Code = -1202「(null)」 UserInfo = {_ kCFStreamPropertySSLClientCertificateState = 0, kCFStreamPropertySSLPeerTrust =, _kCFNetworkCFStreamSSLErrorOriginalValue = -9813,_kCFStreamErrorDomainKey = 3,_kCFStreamErrorCodeKey = -9813,kCFStreamPropertySSLPeerCertificates =( 「」 )}},NSLocalizedDescription =此服務器的證書是無效的。您可能正在連接到一個僞裝成 「202.73.46.176」,它可以把您的機密信息 風險的服務器, NSErrorFailingURLKey = https://202.73.46.176/api/v1/user/find/all/1, NSErrorFailingURLStringKey = https://202.73.46.176/api/v1/user/find/all/1, NSErrorClientCertificateStateKey = 0})

viewDidLoad中

let urlstr: String = "https://202.73.46.176/api/v1/user/find/all/1" 

let request = NSMutableURLRequest(url: NSURL(string: urlstr)! as URL) 
request.httpMethod = "GET" 
let postString = "" 
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() 

方法

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("==============", #function," disposition: ", disposition) 
     print("==============", #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("==============",#function," isServerTrusted: ", isServerTrusted) 
     print("==============", #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) 
     } 
    } 

有人可以幫助我解決這個問題。

回答

0

我發現了一個更好的答案..

創建SecurityCertificateManager

import Foundation 
import Alamofire 


class SecurityCertificateManager { 
    static let sharedInstance = SecurityCertificateManager() 

    let defaultManager: Alamofire.SessionManager = { 
     let serverTrustPolicies: [String: ServerTrustPolicy] = [ 
      "12.3.3.3": .disableEvaluation 
     ] 

     let configuration = URLSessionConfiguration.default 
     configuration.httpAdditionalHeaders = Alamofire.SessionManager.defaultHTTPHeaders 

     return Alamofire.SessionManager(
      configuration: configuration, 
      serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies) 
     ) 
    }() 
} 

,並調用它

 let service = CommanLinksUtility().getServiceAuthUrl() 
     let ticket = UserDefaults.standard.value(forKey: "servicket") as! String 
     let baseUrl = "https://12.3.3.3:5051/api/v1/user/find/all/1" 
     let header = [ "content-type" : "application/json", "url": service, "ticket" : ticket ] 

     SecurityCertificateManager.sharedInstance.defaultManager.request(baseUrl, method: .get, parameters: header as? [String : AnyObject], encoding: URLEncoding.queryString, headers: header) 
      .responseJSON { response in 
       let jsonResult = JSON(data: response.data!) 
       for anItem in jsonResult["result"].arrayValue { 

       } 

} 
0

您可以使用AFNETWorking或Almofire庫

0

你得到這個錯誤,因爲你的服務器沒有SSL證書,因此它不受信任

「此服務器的證書是無效的。你可能會連接到假裝爲「202.73.46.176」的服務器,可能會將您的機密信息置於危險之中。「'

這部分錯誤本身應該足以瞭解發生了什麼。一旦你安裝了一個可信的有效證書,錯誤就會消失。您也可以讓這個可以通過在你的plist

<key>NSAppTransportSecurity</key> 
<dict> 
    <key>NSExceptionDomains</key> 
    <dict> 
     <key>yourdomain.com</key> 
     <dict> 
      <!--Include to allow subdomains--> 
      <key>NSIncludesSubdomains</key> 
      <true/> 
      <!--Include to allow HTTP requests--> 
      <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key> 
      <true/> 
      <!--Include to specify minimum TLS version--> 
      <key>NSTemporaryExceptionMinimumTLSVersion</key> 
      <string>TLSv1.1</string> 
     </dict> 
    </dict> 
</dict> 

指定它忽略,但我會從這樣做的,剛開始的SSL證書爲您的服務器

How can I add NSAppTransportSecurity to my info.plist file?引用了的.plist鍵避免