AFNetworking 3.0中的SSL Pinning

4

我正在使用 AFNetworking 3.0。我的Web服务器有一个由Global Sign签名的https证书。我想在我的iOS应用程序中添加证书固定功能。我的代码如下:

- (AFSecurityPolicy*)customSecurityPolicy{

AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"server" ofType:@"cer"];
NSData *certData = [NSData dataWithContentsOfFile:cerPath];
[securityPolicy setAllowInvalidCertificates:NO];
[securityPolicy setValidatesDomainName:YES];

//securityPolicy.validatesCertificateChain = NO;
[securityPolicy setPinnedCertificates:[NSKeyedUnarchiver unarchiveObjectWithData:certData]];

return securityPolicy;
}

我的客户端代码:

NSString *url = SERVER_URL;
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"application/json"];
manager.securityPolicy = [utils customSecurityPolicy];
[manager GET:url parameters:nil progress:nil success:^(NSURLSessionTask *task, id responseObject) {

    NSLog(@"JSON: %@", responseObject);


} failure:^(NSURLSessionTask *operation, NSError *error) {
    NSLog(@"Error: %@", error);

}];

我们使用Burp Suite作为中间人代理,可以中断请求并监视请求内容。
那么,如何正确实现证书固定?

我也遇到了这个问题。不确定我漏掉了什么。 - arango_86
1个回答

3

这是一个与AFNetworking无关的有效问题,你能找到的仅仅是你所使用的库如何实现curl --cacert操作的方式。

在特定情况下,对于AFNetworking,我的情况是这样的:

let sessionManager = AFHTTPSessionManager()
sessionManager.responseSerializer = AFJSONResponseSerializer()
sessionManager.requestSerializer = AFJSONRequestSerializer()
let configuration = ServiceConfiguration.sharedInstance.configuration
if let policy = configuration?.getSecurityPolicy()?.policy() as? AFSecurityPolicy {
    sessionManager.securityPolicy = policy
}

方法getSecurityPolicy返回一个可选的RequestSecurityPolicy对象(这是一种协议)。

要创建AFSecurityPolicy,我需要:

import AFNetworking

class SSLPinningPolicy: NSObject, RequestSecurityPolicy {

    // MARK: - Private properties -

    private var certificatesDictionary: [String: Data] = [:]

    // MARK: - Initilizers -

    init(certicatePaths: [String]) {
        super.init()
        for path in certicatePaths {
            if let certPath = Bundle.main.path(forResource: path, ofType: "der") {
                let url = URL(fileURLWithPath: certPath)
                do {
                    let data = try Data(contentsOf: url)
                    self.certificatesDictionary[path] = data
                } catch {

                }
            }
        }
    }

    // MARK: - RequestSecurityPolicy delegates -

    func policy() -> AnyObject {
        let policy = AFSecurityPolicy(pinningMode: .certificate)
        policy.allowInvalidCertificates = true
        policy.pinnedCertificates = self.certificates()
        return policy
    }

    func certificates() -> Set<Data> {
        return Set(self.certificatesDictionary.map { $0.value })
    }

}

Plus

如果您想将证书从.pem转换为.der,您可以在终端中使用openssl命令:

openssl x509 -outform der -in MyCertificate.pem -out MyCertificate.der

谢谢提供信息,但是不清楚类SSLPinningPolicy如何用于请求策略。 - arango_86
你可以这样做:_sessionManager.securityPolicy = SSLPinningPolicy(certicatePaths: ["your_certificate_name"]).policy() as! AFSecurityPolicy - landonandrey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接