使用Swift 3和Alamofire 4获取客户端证书以进行相互身份验证 [英] Getting client certificate to work for mutual authentication using Swift 3 and Alamofire 4

查看:349
本文介绍了使用Swift 3和Alamofire 4获取客户端证书以进行相互身份验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在试图弄清楚如何使用Alamofire 4.0和Swift 3.0将p12(我还有PEM证书和密钥,如果需要的话)发送到一个网站进行身份验证。我见过的所有例子都是针对Swift 2.0而不是我正在寻找的。在我的Mac上的safari中,我可以通过将p12放入钥匙串并在safari询问时发送它来访问该网站,因此我知道该部分有效。我不知道是否有人可以帮助我在应用程序中的Alamofire 4.0和Swift 3.0中如何做到这一点。证书也是自签名的。

I am trying to figure out how to use Alamofire 4.0 with Swift 3.0 to send a p12 (i also have the PEM cert and key if need be) to a website for authentication. All the examples i have seen are for Swift 2.0 and not exactly what i'm looking for. In safari on my mac i can access the site by putting the p12 in the keychain and sending it when safari asks so i know that portion works. I don't know if anyone can help me with an example of how to do so in Alamofire 4.0 and Swift 3.0 in an application. The certificates are self signed as well.

有任何想法或帮助吗?我不只是想将证书固定为客户端密钥,并且需要将证书发送到服务器以进行访问...

Any thoughts or help? I am not just looking to pin the certificate as the client key and cert needs to be sent to the server for access...

推荐答案

<我能够让它发挥作用。一些问题陷入了困境。首先,您必须允许IOS接受自签名证书。这需要设置AlamoFire serverTrustPolicy:

I was able to get it to work. A few issues got into the way. First, you have to allow IOS to accept self signed certificates. This requires to set up AlamoFire serverTrustPolicy:

let serverTrustPolicies: [String: ServerTrustPolicy] = [
        "your-domain.com": .disableEvaluation
    ]

self.sessionManager = Alamofire.SessionManager(
        serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies)
    )

从那里,您必须覆盖sessionDidRecieveChallenge以发送客户端证书。因为我想使用p12文件,我修改了一些我在其他地方找到的代码(对不起,我没有源代码)来使用Swift 3.0来导入p12使用基础类:

From there, you have to override the sessionDidRecieveChallenge to send the client certificate. Because i wanted to use a p12 file I modified some code I found elsewhere (sorry i don't have the source anymore) to make is Swift 3.0 to import the p12 using foundation classes:

import Foundation

public class PKCS12  {
    var label:String?
    var keyID:Data?
    var trust:SecTrust?
    var certChain:[SecTrust]?
    var identity:SecIdentity?

    let securityError:OSStatus

    public init(data:Data, password:String) {

        //self.securityError = errSecSuccess

        var items:CFArray?
        let certOptions:NSDictionary = [kSecImportExportPassphrase as NSString:password as NSString]

        // import certificate to read its entries
        self.securityError = SecPKCS12Import(data as NSData, certOptions, &items);

        if securityError == errSecSuccess {
            let certItems:Array = (items! as Array)
            let dict:Dictionary<String, AnyObject> = certItems.first! as! Dictionary<String, AnyObject>;

            self.label = dict[kSecImportItemLabel as String] as? String;
            self.keyID = dict[kSecImportItemKeyID as String] as? Data;
            self.trust = dict[kSecImportItemTrust as String] as! SecTrust?;
            self.certChain = dict[kSecImportItemCertChain as String] as? Array<SecTrust>;
            self.identity = dict[kSecImportItemIdentity as String] as! SecIdentity?;
        }


    }

    public convenience init(mainBundleResource:String, resourceType:String, password:String) {
        self.init(data: NSData(contentsOfFile: Bundle.main.path(forResource: mainBundleResource, ofType:resourceType)!)! as Data, password: password);
    }

    public func urlCredential()  -> URLCredential  {
        return URLCredential(
            identity: self.identity!,
            certificates: self.certChain!,
            persistence: URLCredential.Persistence.forSession);

    }



}

这将允许我导入文件,并将其发送回客户端。

This will allow me to import the file, and send it back to the client.

let cert = PKCS12.init(mainBundleResource: "cert", resourceType: "p12", password: "password");

self.sessionManager.delegate.sessionDidReceiveChallenge = { session, challenge in
        if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodClientCertificate {
            return (URLSession.AuthChallengeDisposition.useCredential, self.cert.urlCredential());
        }
        if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
            return (URLSession.AuthChallengeDisposition.useCredential, URLCredential(trust: challenge.protectionSpace.serverTrust!));
        }
        return (URLSession.AuthChallengeDisposition.performDefaultHandling, Optional.none);
    }

现在,您可以使用sessionManager根据需要创建任意数量的呼叫。

Now you can use the sessionManager to create as many calls as you need to.

作为备注,我还在info.plist中添加了以下内容,以推荐更新iOS功能中的新安全功能:

As a note, i've also added the following to the info.plist as recomended to get around the new security features in newer iOS features:

<key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoads</key>
        <true/>
        <key>NSExceptionDomains</key>
        <dict>
            <key>your-domain.com</key>
            <dict>
                <key>NSIncludesSubdomains</key>
                <true/>
                <key>NSExceptionRequiresForwardSecrecy</key>
                <false/>
                <key>NSExceptionAllowsInsecureHTTPLoads</key>
                <true/>
            </dict>
        </dict>
    </dict>

我希望这有帮助!

这篇关于使用Swift 3和Alamofire 4获取客户端证书以进行相互身份验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆