【问题标题】:Public Pinning is iOS Not working with Almofire公共固定是 iOS 不与 Alamofire 一起使用
【发布时间】:2020-06-25 13:24:33
【问题描述】:

您好,我想使用公钥实现 SSL 固定,我正在使用 Alamofire 4.8.2 下面是代码

func testWithAlmofire(){
    
    let serverTrustPolicies:[String:ServerTrustPolicy] = [
        "example.com": .pinPublicKeys(publicKeys: ServerTrustPolicy.publicKeys(), validateCertificateChain: true, validateHost: true)
    ]
    
    sessionManager = SessionManager(
     serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies)
    )
    
    
    sessionManager.request("https://example.com").response{ res in
        if res.response != nil{
            self.displayAlert(withTitle: "Test Result",
                               message: "Pinning validation succeeded")
        }else{
            self.displayAlert(withTitle: "Test Result",
            message: "Pinning validation Failed")
        }
        
    }
}

如果我做错了什么,请帮助我。

【问题讨论】:

  • 我用 alamofire 失败了很多次,但是当我在应用程序包中包含证书后尝试使用相同的代码时,它就可以工作了。所以我在这里有一个问题:在使用 Alamofire 的公钥固定时,是否需要在应用程序包中包含证书?

标签: ios swift alamofire public-key-pinning


【解决方案1】:

我正在使用类似的东西,我希望这会有所帮助

class NetworkingManager {
static let shared = NetworkingManager()

private init() {
    sharedSession = enableCertificatePinning()
}

var sharedSession: Session?

func enableCertificatePinning() -> Session {
    func getCertificates() -> [SecCertificate] {
        let certs = ["AmazonExample1", "AmazonExample2"]
        var certificates = [SecCertificate]()
        certs.forEach { cert in
            let url = Bundle.main.url(forResource: cert, withExtension: "cer")!
            let localCertificate = try! Data(contentsOf: url) as CFData
            if let certificate = SecCertificateCreateWithData(nil, localCertificate) {
                certificates.append(certificate)
            }
        }
        return certificates
    }
    
    let certificates: [SecCertificate] = getCertificates()
    let trustPolicy = PinnedCertificatesTrustEvaluator(
        certificates: certificates,
        validateHost: true)
    let trustPolicies = [certificateUrl: trustPolicy,
                         "https://example.com": trustPolicy,
                         "https://example2.com": trustPolicy]
    let policyManager = ServerTrustManager(evaluators: trustPolicies)
    return Session(
        configuration: .default,
        serverTrustManager: policyManager)
}
}

你可以这样使用

func exampleRequisiton(someBody: exampleBody,  completion: @escaping (Result<responseExample, NetworkErrors>, _ message: String?) -> Void){

guard let url = URL(string: InviteUrl) else {
    completion(.failure(.invalidUrl), nil)
    return
}

var request = getDefaultRequest(url, .post)
request.httpBody = try? JSONEncoder().encode(someBody)

NetworkingManager.shared.sharedSession?.request(request).validate().responseDecodable(of: DefaultResponse.self, decoder: defaultDecoder) { data in

    switch data.result {
    case let .success(data):
            completion(.success(data), nil)
    case let .failure(error):
        completion(.failure(.genericError), nil)
    }
}
}

我尝试使用一个示例,其中包含申请中使用的所有选项(正文,标题),因为我认为您将需要在某些时候使用它。下面的代码是我单独创建的每个申请中使用的那些对象

var HttpHeaders: HTTPHeaders {
let version = Bundle.main.infoDictionary?["CFBundleVersion"] as? String ?? ""
return [
    "SomeHeader if you have": "example"
]
}

func getDefaultRequest(_ url:URL, _ method:HTTPMethod) -> URLRequest{
var request = URLRequest(url: url)
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpMethod = method.rawValue
request.headers    = HttpHeaders
return request
}

enum NetworkErrors: Error {
case authError
case genericError
case invalidUrl
case serverMessage
}

struct responseExample:Codable{
let systemTimeMillis: Int?
let message: String?
let status: Int?
}

struct exampleBody: Codable {
var example: String
}

【讨论】:

  • HI @bruno 您的回答很好,但您正在使用证书固定,而我正在使用公钥固定。如果您使用公钥在某处实现,请告诉我。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-01
  • 1970-01-01
  • 2016-09-03
  • 1970-01-01
  • 1970-01-01
  • 2014-03-04
相关资源
最近更新 更多