iOS HTTPS证书不受信任解决办法

之前开发App的时候服务端使用的是自签名的证书,导致iOS开发过程中调用HTTPS接口时,证书不被信任

- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler{
    
    /*方法一*/
    if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]){
        NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
        if(completionHandler)
            completionHandler(NSURLSessionAuthChallengeUseCredential,credential);
    }
    
    /*方法二*/
//    SecTrustRef servertrust = challenge.protectionSpace.serverTrust;
//    SecCertificateRef certi= SecTrustGetCertificateAtIndex(servertrust, 0);
//    NSData *certidata = CFBridgingRelease(CFBridgingRetain(CFBridgingRelease(SecCertificateCopyData(certi))));
//    NSString *path = [[NSBundle mainBundle] pathForResource:@"证书名称" ofType:@"cer"];
    NSLog(@"证书 : %@",path);
//    NSData *localCertiData = [NSData dataWithContentsOfFile:path];
//    if ([certidata isEqualToData:localCertiData]) {
//        NSURLCredential *credential = [[NSURLCredential alloc] initWithTrust:servertrust];
//        [challenge.sender useCredential:credential forAuthenticationChallenge:challenge];
//        completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
        NSLog(@"服务端证书认证通过");
//    }else {
//        completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
//        NSLog(@"服务端认证失败");
//    }
    
}

这里有两个方法,第一个是信任所有证书,第二个是把服务端自签名的证书放到本地,类似白名单的样子去加载

源码

HttpRequest.h

//
//  HttpRequest.h
//
//  Created by Michael Zhan on 2017/5/17.
//  Copyright © 2017年 Michael Zhan. All rights reserved.
//

#import <Foundation/Foundation.h>

static NSString * const baseUrl = @"http://";

typedef void (^SuccessBlock)(NSString * data);
typedef void (^FailureBlock)(NSError * error);

@interface HttpRequest : NSObject <NSURLSessionTaskDelegate>

- (void)getWithDict:(NSString *)paramUrl NSDictionary:(NSDictionary *)paramDicet success:(SuccessBlock)successBlock failure:(FailureBlock)failureBlock;

- (void)postWithDict:(NSString *)paramUrl NSDictionary:(NSDictionary *)paramDicet success:(SuccessBlock)successBlock failure:(FailureBlock)failureBlock;

- (void)getWithString:(NSString *)paramUrl NSString:(NSString *)paramString success:(SuccessBlock)successBlock failure:(FailureBlock)failureBlock;

- (void)postWithString:(NSString *)paramUrl NSString:(NSString *)paramString success:(SuccessBlock)successBlock failure:(FailureBlock)failureBlock;

- (void)postWithDict2String:(NSString *)paramUrl NSDictionary:(NSDictionary *)paramDicet success:(SuccessBlock)successBlock failure:(FailureBlock)failureBlock;

@end

HttpRequest.m

//
//  HttpRequest.m
//
//  Created by Michael Zhan on 2017/5/17.
//  Copyright © 2017年 Michael Zhan. All rights reserved.
//

#import "HttpRequest.h"

@implementation HttpRequest

- (void)getWithDict:(NSString *)paramUrl NSDictionary:(NSDictionary *)paramDicet success:(SuccessBlock)successBlock failure:(FailureBlock)failureBlock{
    
    NSMutableString * mutableStringUrl = [[NSMutableString alloc] initWithString:paramUrl];
    [mutableStringUrl appendString:[HttpRequest convertToJsonData:paramDicet]];
    
    NSLog(@"url %@",mutableStringUrl);
    
    NSURL * url = [NSURL URLWithString:[mutableStringUrl stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]];
    
    NSURLRequest * request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:10];
    
    //2程序自动安装证书的方式
    NSURLSession * session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[[NSOperationQueue alloc]init]];
    
    NSURLSessionDataTask * dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        if (error) {
            failureBlock(error);
        } else {
            NSString * result = [[NSString alloc] initWithData:data  encoding:NSUTF8StringEncoding];
            successBlock(result);
        }
    }];
    [dataTask resume];
    
}

- (void)postWithDict:(NSString *)paramUrl NSDictionary:(NSDictionary *)paramDicet success:(SuccessBlock)successBlock failure:(FailureBlock)failureBlock{
    
    NSURL * url = [NSURL URLWithString:paramUrl];
    
    NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:url
                    cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:100];
    
    request.HTTPMethod = @"POST";
    NSString * jsonStr = [HttpRequest convertToJsonData:paramDicet];
    request.HTTPBody = [jsonStr dataUsingEncoding:NSUTF8StringEncoding];
    
    //2程序自动安装证书的方式
    NSURLSession * session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[[NSOperationQueue alloc]init]];
    
    NSURLSessionDataTask * dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        if (error) {
            failureBlock(error);
            [session finishTasksAndInvalidate];
        } else {
            NSString * result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
            successBlock(result);
            [session finishTasksAndInvalidate];
        }
    }];
    [dataTask resume];
}

- (void)postWithDict2String:(NSString *)paramUrl NSDictionary:(NSDictionary *)paramDicet success:(SuccessBlock)successBlock failure:(FailureBlock)failureBlock{
    
    NSURL * url = [NSURL URLWithString:paramUrl];
    
    NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:100];
    
    request.HTTPMethod = @"POST";
    NSString * jsonStr = [NSString stringWithFormat:@"%@",paramDicet];
    request.HTTPBody = [jsonStr dataUsingEncoding:NSUTF8StringEncoding];
    request.timeoutInterval = 10;
    request.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
    
    
    //2程序自动安装证书的方式
    NSURLSession * session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[[NSOperationQueue alloc]init]];
    
    NSURLSessionDataTask * dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        if (error) {
            failureBlock(error);
            [session finishTasksAndInvalidate];
        } else {
            NSString * result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
            successBlock(result);
            [session finishTasksAndInvalidate];
        }
    }];
    [dataTask resume];
}

- (void)getWithString:(NSString *)paramUrl NSString:(NSString *)paramString success:(SuccessBlock)successBlock failure:(FailureBlock)failureBlock{
   
    NSMutableString * mutableStringUrl = [[NSMutableString alloc] initWithString:paramUrl];
    [mutableStringUrl appendString:paramString];
    
    NSLog(@"url %@",mutableStringUrl);
    NSURL * url =[NSURL URLWithString:[mutableStringUrl stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]];
    
    NSURLRequest * request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:10];
    
    //2程序自动安装证书的方式
    NSURLSession * session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[[NSOperationQueue alloc]init]];
    
    NSURLSessionDataTask * dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        if (error) {
            failureBlock(error);
            [session finishTasksAndInvalidate];
        } else {
            NSString * result = [[NSString alloc] initWithData:data  encoding:NSUTF8StringEncoding];
            successBlock(result);
            [session finishTasksAndInvalidate];
        }
    }];
    [dataTask resume];

}

- (void)postWithString:(NSString *)paramUrl NSString:(NSString *)paramString success:(SuccessBlock)successBlock failure:(FailureBlock)failureBlock{
    
    NSURL * url = [NSURL URLWithString:paramUrl];
    
    NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:100];
    request.HTTPMethod = @"POST";
    request.HTTPBody = [paramString dataUsingEncoding:NSUTF8StringEncoding];
    request.timeoutInterval = 10;
    request.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
    
    //2程序自动安装证书的方式
    NSURLSession * session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[[NSOperationQueue alloc]init]];

    NSURLSessionDataTask * dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        if (error) {
            failureBlock(error);
             [session finishTasksAndInvalidate];
        } else {
            NSString * result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
            successBlock(result);
             [session finishTasksAndInvalidate];
        }
    }];
    [dataTask resume];
}

+ (NSString *)convertToJsonData:(NSDictionary *)dict{
    NSError *error;
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dict options:NSJSONWritingPrettyPrinted error:&error];
    NSString *jsonString;
    if (!jsonData) {
        NSLog(@"%@",error);
    }else{
        jsonString = [[NSString alloc]initWithData:jsonData encoding:NSUTF8StringEncoding];
    }
    NSMutableString *mutStr = [NSMutableString stringWithString:jsonString];
    NSRange range = {0,jsonString.length};
    //去掉字符串中的空格
    [mutStr replaceOccurrencesOfString:@" " withString:@"" options:NSLiteralSearch range:range];
    NSRange range2 = {0,mutStr.length};
    //去掉字符串中的换行符
    [mutStr replaceOccurrencesOfString:@"\n" withString:@"" options:NSLiteralSearch range:range2];
    return mutStr;
}

- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler{
    
    /*方法一*/
    if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]){
        NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
        if(completionHandler)
            completionHandler(NSURLSessionAuthChallengeUseCredential,credential);
    }
    
    /*方法二*/
//    SecTrustRef servertrust = challenge.protectionSpace.serverTrust;
//    SecCertificateRef certi= SecTrustGetCertificateAtIndex(servertrust, 0);
//    NSData *certidata = CFBridgingRelease(CFBridgingRetain(CFBridgingRelease(SecCertificateCopyData(certi))));
//    NSString *path = [[NSBundle mainBundle] pathForResource:@"zwp" ofType:@"cer"];
    NSLog(@"证书 : %@",path);
//    NSData *localCertiData = [NSData dataWithContentsOfFile:path];
//    if ([certidata isEqualToData:localCertiData]) {
//        NSURLCredential *credential = [[NSURLCredential alloc] initWithTrust:servertrust];
//        [challenge.sender useCredential:credential forAuthenticationChallenge:challenge];
//        completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
        NSLog(@"服务端证书认证通过");
//    }else {
//        completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
//        NSLog(@"服务端认证失败");
//    }
    
}

@end
### Charles Proxy 安装证书后未知错误 (Unknown) 的解决方案 当使用 Charles 抓包时,如果出现 `<unknown>` 提示,通常是因为目标应用程序或浏览器未正确信任 Charles 的 SSL 证书。以下是针对该问题的具体分析和解决方法: #### 1. 正确安装并信任 Charles 根证书 确保已按照官方文档完成根证书的安装过程。具体操作如下: - 打开 Charles 软件,点击菜单栏 `Help > SSL Proxying > Save Charles Root Certificate`,下载 Charles 的根证书文件。 - 将此 `.crt` 文件导入至需要抓包的目标设备上,并手动安装它[^1]。 对于 Android 和 iOS 设备而言,在安装完成后还需要进一步确认系统是否完全信任该 CA 证书。例如在 iPhone 上需进入 **设置 -> 通用 -> 关于本机 -> 信任存储的开发者企业级应用** 来激活新添加的信任关系。 #### 2. 配置 SSL 加密流量代理规则 除了基础网络层面上的数据拦截外,还需特别指定哪些域名下的 HTTPS 请求应该被解码处理。这一步骤可通过调整软件内部参数实现: - 进入 Charles 主界面,依次导航到路径 `Proxy > SSL Proxying Settings...` - 添加新的条目定义特定主机名及其端口号组合作为例外情况对待;比如可以输入通配符形式如 `"*.example.com"` 表达任意子域都适用当前策略[^4]。 #### 3. 启用允许加载混合内容选项 部分现代移动端 APP 实现了更严格的安全机制,默认拒绝任何未经认证机构签发的有效凭证之外的所有连接尝试。因此即使完成了上述两步也可能依旧面临访问受限的局面。此时建议检查是否存在类似开关控制此项行为模式的可能性——即所谓的“忽略无效证书警告”或者“支持非标准加密协议版本”。 某些情况下可能涉及到修改操作系统级别的全局偏好设定才能生效。以安卓为例,则前往 **安全->高级->网络安全配置**, 开启对应功能项即可[^3]。 #### 4. 排查其他潜在干扰因素 尽管采取以上措施之后大部分场景下都能够恢复正常工作状态, 过仍排除个别特殊情形的存在。假如发现即便遵循全部指导方针仍然无法解决问题的话, 可能要考虑以下几个方面: - 应用本身内置了自己的 pinning 方案来锁定预期使用的公钥哈希值列表, 导致第三方中间人攻击变得可能. - 或者存在额外的企业级 MDM(Mobile Device Management) 解决方案施加限制条件阻止未经授权的操作. 在这种极端状况面前, 唯一可行的办法或许是联系开发团队获取协助或是寻找替代性的调试手段[^5]. ```bash # 示例命令用于查看openssl版本以及支持算法详情 $ openssl version -a OpenSSL 1.1.1f 31 Mar 2020 built on: Mon Apr 6 17:19:28 2020 UTC platform: darwin64-x86_64-llvm options: bn(64,64) rc4(char) des(long) idea(int) blowfish(ptr) compiler: clang -I/usr/local/Cellar/openssl@1.1/1.1.1g/include -DOPENSSL_PIC -DZLIB_SHARED -DZLIB -DDSO_DLFCN -DHAVE_OPENSSL_RAND_SEED_OS -DL_ENDIAN -Wall -O2 -pipe -arch x86_64 -mmacosx-version-min=10.12 -Wa,--noexecstack -Qunused-arguments -Wl,-headerpad_max_install_names -Wl,-dead_strip_dylibs OPENSSLDIR: "/usr/local/etc/openssl@1.1" ENGINESDIR: "/usr/local/lib/engines-1.1" Seeding source: os-specific ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值