当前位置: 首页 > news >正文

Object-C 中的证书校验

什么是证书校验?

证书校验是客户端、服务器建立信任的一种手段,一般发生在建立网络连接的时候,比如:

  • HTTPS连接 - 服务器要求验证SSL/TLS证书
  • HTTP代理认证 - 需要代理服务器认证
  • HTTP基本认证 - 服务器要求用户名密码
  • 客户端证书 - 服务器要求客户端提供证书

证书校验分类

客户端校验服务器证书:客户端对服务器发来的证书进行校验(常用)

服务器校验客户端证书:服务器对客户端发出的证书进行校验

证书校验流程

              HTTPS握手流程客户端                        服务器|                             ||---- 1. ClientHello -------->|  "我想建立HTTPS连接"|                             ||<--- 2. ServerHello ---------|  "好的,这是我的证书 📜"|                             ||                             |👆 此时触发 NSURLAuthenticationMethodServerTrust客户端需要验证:✅ 这个证书是不是CA签发的?✅ 证书有没有过期?✅ 证书的域名是否匹配?✅ 证书链是否完整?|                             ||---- 3. Finished ----------->|  "我信任你的证书,继续"|                             ||<--- 4. 加密通信 ------------|
服务器                              客户端|                                   |📜 拥有证书文件                      |(server.crt + server.key)          ||                                   ||-------- 发送证书 📜 ------------->||    (只发送公钥证书,不发送私钥)    ||                                   ||                                   | 👀 接收到证书|                                   | 📋 验证步骤:|                                   |   1. 检查证书颁发者|                                   |   2. 检查证书有效期|                                   |   3. 检查域名匹配|                                   |   4. 检查证书链|                                   ||                                   | ✅ 创建信任凭据|                                   |    (不是新证书!)|                                   ||<-------- 继续连接 -----------------|

方法释义、相关参数解释


/// - Parameters:
///   - session:本次网络连接
///   - challenge:需要验证授权的内容,包括服务器发来的证书
///   - completionHandler:授权之后,告诉系统是信任该服务器,还是不信任该服务器,
///    -NSURLSessionAuthChallengeDisposition:操作的枚举值,cancel表示拒绝,trust表示信任
///    -NSURLCredential:操作的凭据,有了凭据,系统才能信任这么操作没有问题- (void)URLSession:(NSURLSession *)session 
didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler

参数详解:

Challenge:需要验证的内容详情,其中里面的,里面的protectionSpace参数,表示详细内容NSURLProtectionSpace *protectionSpace:authenticationMethod:表示验证当前连接的方法,比较常用地就是,表示验证服务器发来的证书NSURLAuthenticationMethodServerTrustSecTrustRef serverTrust:表示服务器发来的证书,用来执行X.509证书的计算completionHandler:验证完之后的回调,它内部是调用的系统的方法,根据传递的参数,来决定是否要信任本次连接//本次校验的结果
NSURLSessionAuthChallengeDispositiontypedef NS_ENUM(NSInteger, NSURLSessionAuthChallengeDisposition) {// 1️⃣ 使用提供的凭据NSURLSessionAuthChallengeUseCredential = 0,// 含义:我已经验证了,使用我提供的credential继续// 场景:自定义证书验证通过,信任服务器// 2️⃣ 使用系统默认处理NSURLSessionAuthChallengePerformDefaultHandling = 1,// 含义:我不处理,交给系统默认逻辑// 场景:使用iOS系统的证书验证(信任系统根证书)// 3️⃣ 取消认证挑战NSURLSessionAuthChallengeCancelAuthenticationChallenge = 2,// 含义:拒绝这个证书,取消连接// 场景:证书验证失败,不信任服务器// 4️⃣ 拒绝该保护空间NSURLSessionAuthChallengeRejectProtectionSpace = 3// 含义:拒绝这个认证保护空间,但可以尝试其他凭据// 场景:用户名密码错误,允许重试
};

校验示例

完全自定义校验方法
ODNetwork *network = [[ODNetwork alloc] init];// 设置自定义验证器
network.sessionDidReceiveAuthenticationChallenge = ^NSURLSessionAuthChallengeDisposition(NSURLSession *session,NSURLAuthenticationChallenge *challenge,NSURLCredential *__autoreleasing *credential) {// 完全自定义逻辑,比如:// - 测试环境信任所有证书// - 特殊的证书绑定策略// - 用户手动选择是否信任if (isTestEnvironment) {*credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];return NSURLSessionAuthChallengeUseCredential;}return NSURLSessionAuthChallengePerformDefaultHandling;
};
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler {NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;NSURLCredential *credential = nil;if (self.sessionDidReceiveAuthenticationChallenge) {disposition = self.sessionDidReceiveAuthenticationChallenge(session, challenge, &credential);} else {if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {if ([self.securityPolicy evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:challenge.protectionSpace.host]) {//在进行服务器信任的身份验证时,客户端需要验证服务器的证书有效性。当收到一个服务器信任的身份验证挑战时,可以使用 `NSURLCredential` 类的 `credentialForTrust:` 方法来创建一个凭据对象。credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];if (credential) {disposition = NSURLSessionAuthChallengeUseCredential;} else {disposition = NSURLSessionAuthChallengePerformDefaultHandling;}} else {disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;}} else {disposition = NSURLSessionAuthChallengePerformDefaultHandling;}}if (completionHandler) {completionHandler(disposition, credential);}
}
自定义校验策略(内置证书校验)

校验服务端的证书,和客户端内置的证书,是否一样

// 场景:生产环境使用证书绑定(Certificate Pinning)// 1. 配置 SecurityPolicy
ODSecurityPolicy *policy = [ODSecurityPolicy policyWithPinningMode:ODSSLPinningModeCertificate];
policy.pinnedCertificates = [self loadPinnedCertificates];
network.securityPolicy = policy;// 2. 发起HTTPS请求
[network flushEvent:event immediately:YES];// 3. 触发证书验证
- (void)URLSession:(NSURLSession *)session 
didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler {// 没有自定义验证器,走默认流程if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {// 服务器证书SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;// 使用 SecurityPolicy 验证// 会检查证书是否在 pinnedCertificates 列表中if ([self.securityPolicy evaluateServerTrust:serverTrust forDomain:@"api.example.com"]) {// ✅ 证书匹配,信任NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust];completionHandler(NSURLSessionAuthChallengeUseCredential, credential);} else {// ❌ 证书不匹配,拒绝(防止中间人攻击)completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);}}
}
客户端自己证书校验
- (void)URLSession:(NSURLSession *)session 
didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler {// 服务器要求客户端证书if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodClientCertificate]) {// 从钥匙串加载客户端证书SecIdentityRef identity = [self loadClientCertificate];NSURLCredential *credential = [NSURLCredential credentialWithIdentity:identitycertificates:nilpersistence:NSURLCredentialPersistenceForSession];completionHandler(NSURLSessionAuthChallengeUseCredential, credential);}
}

http://www.dtcms.com/a/540385.html

相关文章:

  • PCIe协议之 SMBus 信号线
  • 赋能国防航天,数字孪生IOC ProMAX版如何重塑智能指挥与运维新标杆
  • GXDE 内核管理器1.0.0——支持 deepin20、23
  • 声呐到底怎么选?
  • 做购物网站是怎么连接银行公众号怎么做小程序
  • 吉林省城乡建设官方网站网站后台修改教程
  • saas模板使用教程
  • 在CentOS 7.9上升级OpenSSH到9.9p2
  • asp 网站支持多语言想建立一个网站
  • Spring Boot3零基础教程,Spring Security 简介,笔记80
  • 调试技巧:从 IDE 调试到生产环境定位问题,提升调试效率的全方位指南
  • 服务器和docker容器时间不一致相关问题
  • Vue+Element Plus 表格工具栏组件:动态按钮 + 搜索控制的优雅实现​
  • 上海网站建设平台什么是seo标题优化
  • 网络编程之WebSocket(1)
  • Electron_Vue3 自定义系统托盘及退出二次确认
  • 为什么 Electron 项目推荐使用 Monorepo 架构 [特殊字符][特殊字符][特殊字符]
  • BLIP2 工业实战(一):从零实现 LAVIS 跌倒检测 (微调与“踩坑”指南)
  • NPM下载和安装图文教程(附安装包)
  • 2025 年台湾 5 大 CDP 平台推荐比较
  • 【数据结构】栈(Stack)详解——数据结构的“后进先出”
  • Java 大视界 -- Java 大数据在智能金融理财产品风险评估与个性化配置中的应用
  • Bootstrap4 安装使用指南
  • 怎么建设购物网站免费入驻的网站设计平台
  • vue2 将接口返回数据导出为 excel 文件
  • Java 使用 Spire.XLS 库合并 Excel 文件实践
  • Vultr × Caddy 多站点反向代理 + 负载均衡网关系统实战
  • 【数据结构】(C++数据结构)查找算法与排序算法详解
  • @pytest.fixture函数怎么传变量参数
  • Excel高性能异步导出完整方案!