如何在Objective-C中使用AFNetworking 3实现SSL Pinning(公钥模式)?
用AFNetworking 3实现SSL Pinning(AFSSLPinningModePublicKey模式)
别担心,AFNetworking 3完全支持AFSSLPinningModePublicKey模式的SSL固定,可能你在文档里没挖到具体的实现细节,我来给你补全完整的实现步骤和代码:
第一步:准备服务器公钥
你需要先获取目标服务器的RSA公钥,可以通过两种方式获取:
- 从服务器的SSL证书中导出公钥(
.der格式或者直接提取PEM格式的字符串) - 直接访问服务器,通过openssl命令提取:
openssl s_client -connect yourdomain.com:443 | openssl x509 -pubkey -noout
第二步:完整配置AFHTTPSessionManager和AFSecurityPolicy
补全你未写完的代码,这里是完整的实现:
NSString *baseUrl = @"https://your-target-domain.com"; AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc] initWithBaseURL:[NSURL URLWithString:baseUrl]]; // 初始化公钥固定模式的安全策略 AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey]; // 关键配置:根据你的需求调整以下参数 // 如果服务器证书是自签名的,需要设置为YES;正式环境建议NO securityPolicy.allowInvalidCertificates = NO; // 是否验证域名,正式环境必须设为YES,防止中间人攻击 securityPolicy.validatesDomainName = YES; // 添加你准备好的公钥到策略中 // 方式1:从本地公钥文件导入(比如你把公钥存为public_key.der放在项目里) NSData *publicKeyData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"public_key" ofType:@"der"]]; securityPolicy.pinnedPublicKeys = [NSSet setWithObject:publicKeyData]; // 方式2:如果是PEM格式的公钥字符串,需要先转换为NSData再添加 // NSString *pemPublicKey = @"-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----"; // NSData *publicKeyData = [self convertPEMToDER:pemPublicKey]; // securityPolicy.pinnedPublicKeys = [NSSet setWithObject:publicKeyData]; // 把安全策略赋值给manager manager.securityPolicy = securityPolicy;
第三步:可选的公钥转换方法(如果用PEM格式)
如果你的公钥是PEM格式的字符串,需要先转换成DER格式的NSData,这里给你一个转换方法:
- (NSData *)convertPEMToDER:(NSString *)pemString { NSString *cleanedString = [pemString stringByReplacingOccurrencesOfString:@"-----BEGIN PUBLIC KEY-----" withString:@""]; cleanedString = [cleanedString stringByReplacingOccurrencesOfString:@"-----END PUBLIC KEY-----" withString:@""]; cleanedString = [cleanedString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; return [[NSData alloc] initWithBase64EncodedString:cleanedString options:NSDataBase64DecodingIgnoreUnknownCharacters]; }
常见问题提示
- 公钥不匹配:如果请求报错,先检查你导入的公钥是否和服务器当前使用的公钥一致,服务器证书更新后公钥也会变化
- 域名验证问题:
validatesDomainName设为NO会降低安全性,除非是测试自签名证书的场景,正式环境一定要开启 - 证书链问题:如果服务器使用的是证书链,AFNetworking会自动验证整个链,但公钥固定只需要验证最终的服务器公钥即可
内容的提问来源于stack exchange,提问作者devtorasia
相关产品推荐
相关产品推荐

