2017-07-12 72 views
10

Swift iOS uygulamasında harika çalışan genel anahtar kilitleme kodum var.URLAuthenticationChallenge program aracılığıyla oluştururken nil olmayan bir serverTrust değeri nasıl alabilirim?

Şu anda ağ bağlantısı/gerçek canlı sunucuya ihtiyaç duymadan genel anahtar kodlama kodunu test edecek yapı birimi testleri üzerinde çalışıyorum. Neredeyse çalışıyorum, ancak null olmayan bir serverTrust olan bir URLAuthenticationChallenge programsal olarak nasıl oluşturacağımı anlayamıyorum? Tüm Apple belgeleri, kimlik doğrulama yönteminiz NSURLAuthenticationMethodServerTrust ise, bunun null olmaması gerektiğini belirtir. Aşağıdaki örnekte URLCredential'ı oluşturmak için yerel makinemden üretilen p12 ve cer dosyalarını kullanıyorum. Ne yaptığımın bir önemi yok, challenge.protectionSpace.serverTrust her zaman geri geliyor.

let protectionSpace = URLProtectionSpace(host: "mockSession", 
               port: 0, 
               protocol: "https", 
               realm: nil, 
         authenticationMethod: NSURLAuthenticationMethodServerTrust) 

var urlCredential:URLCredential? 
if let p12Data = try? Data(contentsOf: URL(fileURLWithPath: Bundle.init(for: type(of: self)).path(forResource: "cm7justindomnit", ofType: "p12") ?? "")), 
    let cerData = try? Data(contentsOf: URL(fileURLWithPath: Bundle.init(for: type(of: self)).path(forResource: "cm7justindomnit", ofType: "cer") ?? "")){ 
    let options: NSDictionary = [kSecImportExportPassphrase:"password"] 
    var items: CFArray? 
    let _ = SecPKCS12Import(p12Data as CFData, options, &items) 
    if let items = items { 
     let objectsData = Data.init(from: CFArrayGetValueAtIndex(items, 0)) 
     let objects = objectsData.toArray(type: CFDictionary.self).first 
     let secIdentityData = Data.init(from: CFDictionaryGetValue(objects, Unmanaged.passUnretained(kSecImportItemIdentity).toOpaque())) 
     if let secIdentity = secIdentityData.toArray(type: SecIdentity.self).first { 
      if let secCertifiate = SecCertificateCreateWithData(kCFAllocatorDefault, cerData as CFData) { 
       urlCredential = URLCredential(identity: secIdentity, certificates: [secCertifiate], persistence: .forSession) 
      } 
     } 
    } 
} 

let challenge = URLAuthenticationChallenge(protectionSpace: protectionSpace, 
                proposedCredential: urlCredential, 
                previousFailureCount: 0, 
                failureResponse: nil, 
                error: nil, 
                sender: self) 

Ben UnsafeBufferPointers işlemek için bir veri uzantısı vardır.

extension Data { 

    init<T>(from value: T) { 
     var value = value 
     self.init(buffer: UnsafeBufferPointer(start: &value, count: 1)) 
    } 

    func to<T>(type: T.Type) -> T { 
     return self.withUnsafeBytes { $0.pointee } 
    } 

    func toArray<T>(type: T.Type) -> [T] { 
     return self.withUnsafeBytes { 
      [T](UnsafeBufferPointer(start: $0, count: self.count/MemoryLayout<T>.stride)) 
     } 
    } 
} 

cevap

0

Hep didReceive challenge uzakta test ettiğiniz sınıftan kullanılan yöntem taşımak ve bazı protokol iletişimi ile bağlayabilirsiniz. Ardından, gerektiğinde yöntemlerini çağır. Örneğin: testinde

if let serverTrust = challenge.protectionSpace.serverTrust { 
    var secresult = SecTrustResultType(kSecTrustResultInvalid) 
    let status = SecTrustEvaluate(serverTrust, &secresult) 

    if status == errSecSuccess { 
     if let certificate = SecTrustGetCertificateAtIndex(serverTrust, 0) { 
      if self.checker.isOkCertificate(certificate) { ... } 
     } 
    } 
} 

Taşı kontrol kodu

class Checker: CheckerProtocol { ... } 

Meenwhile

için: Eğer sertifika ile bazı mantık test etmek gerekirse

protocol CheckerProtocol { 
    // or event simplier 
    func isOkCertificate(_ certificate:) -> Bool 
} 

sadece doğrudan denetimi bağımlılığına geçmek hedef:

let certificate = // init right/wrong one 
let checker = Checker() 
XCTAssert[True|False](checker.isOkCertificate(certificate)) 
+0

T Cevabınız için sizi hantal, ancak öneriniz hala sertifika çıkarma ve karşılaştırma yaparak kodu test etmeme izin vermiyor. Ben test etmeye çalıştığım şey bu. SecTrustEvaluate ve SecTrustGetCertificateAtIndex'i çağırdığım satırlara geldiğimde (bu, özel kod olarak gösterilmiyor), nil olmayan bir serverTrust'a ihtiyacım var, böylece yaprak sertifikalarını inceleyebilirim. Yine de teşekkürler! –

+0

@JustinDomnitz güncellendi. Bak, iki sınıfı birbirine bağlamak için sadece sertifika kullanmanız gerekmiyor, Protokolleri kullanmak gereklidir, böylece birim testlerinizdeki sahtekarlarla değiştirebilirsiniz. – Astoria

+0

Takip için teşekkürler. Bana yardım edip edemeyeceğini görmek için cevabınıza erişmem gerekiyor. Bunu yaptıktan sonra biraz daha notlar yapacağım. Bu arada, sana ödül verdim. Teşekkür ederim! –