简体   繁体   English

如何使用 TLS 和自签名证书在本地服务器中使用 Alamofire 安全上传文件?

[英]How to securely upload files with Alamofire in a local server using TLS and self-signed certificates?

I am able to successfuly upload files on a local server (implemented in node.js) using Alamofire 5 with ATS Allow Arbitrary Loads and the following snippet:我能够使用带有 ATS Allow Arbitrary Loads的 Alamofire 5 和以下代码段成功地在本地服务器上上传文件(在 node.js 中实现):

struct httpBinResponse: Decodable { let url: String }
let url = "http://10.0.0.2:443/upload"
let path = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
guard let fileURL : URL = path.appendingPathComponent("F06F34EC-0BFD-4201-8405-7CED956CA299.zip") else {return}
AF.upload(multipartFormData:
    {(multipart) in multipart.append(fileURL, withName: "file", fileName: fileURL.lastPathComponent, mimeType: "application/octet-stream" )},
    to: url)
    .responseDecodable(of: httpBinResponse.self) { response in
        debugPrint(response)
}

I was able to switch to HTTPS in the local server and I can upload files with Postman using self-signed ca/client and server certificates.我能够在本地服务器中切换到 HTTPS,并且可以使用自签名的 ca/客户端和服务器证书上传带有 Postman 的文件。 I have read posts for self-signed certificate pinning but I am not sure if I need to pin or authenticate.我已阅读有关自签名证书固定的帖子,但我不确定是否需要固定或验证。

What is the best practice that involves TLS in a local server with self-signed certificates and Alamofire?在具有自签名证书和 Alamofire 的本地服务器中涉及 TLS 的最佳实践是什么?

EDIT 5/4/20: Following suggestions from different sources, I made progress by adding the following:编辑 5/4/20:根据不同来源的建议,我通过添加以下内容取得了进展:

struct Certificates {
    static let ca: SecCertificate = Certificates.certificate(filename: "ca")

    private static func certificate(filename: String) -> SecCertificate {
        let filePath = Bundle.main.path(forResource: filename, ofType: "der")!
        let data = try! Data(contentsOf: URL(fileURLWithPath: filePath))
        let certificate = SecCertificateCreateWithData(nil, data as CFData)!
        return certificate
    }
}

And in inside my class I have added:在我的 class 里面我添加了:

private let secureSession: Session = {
    let certificates : [SecCertificate] = [Certificates.ca]

    let pinnedCertEvaluator = PinnedCertificatesTrustEvaluator(certificates: certificates,
                                                               acceptSelfSignedCertificates: true,
                                                               performDefaultValidation: false,
                                                               validateHost: false)
    let manager = ServerTrustManager(evaluators: ["10.0.0.2": pinnedCertEvaluator])
    let configuration = URLSessionConfiguration.af.default

    return Session(configuration: configuration, serverTrustManager: manager)
}()

After adding the above I was able to use https to upload the files.添加上述内容后,我可以使用 https 上传文件。 I am not sure why I have to set performDefaultValidation and validateHost to false to avoid getting Alamofire.AFError.serverTrustEvaluationFailed .我不知道为什么我必须将performDefaultValidationvalidateHost设置为false以避免得到Alamofire.AFError.serverTrustEvaluationFailed Is this the right way to go?这是 go 的正确方法吗? Another point I am trying to figure out is why do I only need the ca root certificate for pinning?我想弄清楚的另一点是为什么我只需要 ca 根证书来固定?

I've implemented something similar:我已经实现了类似的东西:

  1. Copy your self signed certificate into your XCode project.将您的自签名证书复制到您的 XCode 项目中。 Lets call this certificate "myCert.der"让我们将此证书称为“myCert.der”

  2. Setup an Alamofire secure session manager with your signed certificate.使用您的签名证书设置 Alamofire 安全 session 管理器。 It will be something like this.它会是这样的。

     var secureSessionManager = Alamofire.SessionManager() func configureAlamoFireSSLPinning() { let pathToCert = Bundle.main.path(forResource: "myCert", ofType: "der") let localCertificate:NSData = NSData(contentsOfFile: pathToCert.), if #available(iOS 10.3: *) { let STP = ServerTrustPolicy,pinPublicKeys( publicKeys, [SecCertificateCopyPublicKey(SecCertificateCreateWithData(nil: localCertificate),):]. validateCertificateChain: true. validateHost: true) let serverTrustPolicies = [ "myhost.com", STP ] secureSessionManager = Alamofire:SessionManager( configuration: URLSessionConfiguration.default, serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies)) } }
  3. Call the function to setup your secure session manager: configureAlamoFireSSLPinning()调用 function 来设置您的安全 session 管理器: configureAlamoFireSSLPinning()

  4. Make your requests using this alamofire secure session manager.使用此 alamofire 安全 session 管理器提出您的请求。 All requests made through this manager will be secure:通过此管理器提出的所有请求都是安全的:

     secureSessionManager.request("https://host.com/myrequest", method:.get).responseJSON { response in switch response.result { case.success(let value): //Do stuff case.failure(let error): print(error) } }

    For more information, you can visit Alamofire's documentation on security: https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#security有关更多信息,您可以访问 Alamofire 的安全文档: https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#security

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM