什么是双向认证呢?简而言之,就是服务器端对请求它的客户端要进行身份验证,客户端对自己所请求的服务器也会做身份验证。服务端一旦验证到请求自己的客户端为不可信任的,服务端就拒绝继续通信。客户端如果发现服务端为不可信任的,那么也中止通信。
双向认证的算法理论是RSA,(点击此处了解RSA算法原理)。 双向认证具体又是通过安全证书的方式来实现的,安全证书可用openssl或java程序来生成,用于双向认证的安全证书中保存了密钥对,证书颁发机构信 息,签名信息,签名算法,颁发对象,有效期等信息。双向认证中安全证书分为服务器端证书和客户端证书,用服务器端证书中的私钥对客户端证书进行签名,并把 签名信息写到客户端证书中,就得到了被服务端信任的证书。当客户端请求该服务端时,服务端为拿到客户端证书信息,然后取出证书中的签名信息,用服务器端证 书的公钥验证,如果发现这个客户端证书确实是服务器端证书签名颁发的,那么通信就可以继续进行,否则中断。
上面简单介绍了一下双向认证和安全证书,那么我们现在开始正题。
首先,我们用java生成一个服务器端证书库myserverdomain和客户端证书库wenfeng.xu,取出服务器端的证书库中的证书为客户端证 书库签名并生成PKCS12格式的证书文件wenfeng.xu.pfx。然后我们将服务器端证书配置在应用服务器中,并启用客户端认证。以jetty为 例,以下为配置方法:
启动应用服务器,并用与生成服务端证书一致的域名访问应用(注意这点非常重要,ASIHTTPRequest如果不这么做是会报错的,这个域名可以随便 取,只要更改系统的host配置,让域名指向服务端ip就行了)。如果你用浏览器访问已启动的应用,如果看到以下信息,就可以开始oc客户端的编码了。
在引入了ASIHTTPRequest框架的项目中新建测试类Https.m
@implementation Https + (void)testClientCertificate { NSURL *httpsUrl = [NSURL URLWithString:@"https://www.myserverdomain.com:8443/smvcj"];//访问路径 ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:httpsUrl]; SecIdentityRef identity = NULL; SecTrustRef trust = NULL; //绑定证书,证书放在Resources文件夹中 NSData *PKCS12Data = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"wenfeng.xu" ofType:@"pfx"]];//证书文件名和文件类型 [Https extractIdentity:&identity andTrust:&trust fromPKCS12Data:PKCS12Data]; request = [ASIHTTPRequest requestWithURL:httpsUrl]; [request setClientCertificateIdentity:identity];//设定访问路径 [request setValidatesSecureCertificate:NO];//是否验证服务器端证书,如果此项为yes那么服务器端证书必须为合法的证书机构颁发的,而不能是自己用openssl 或java生成的证书 [request startSynchronous]; NSError *error = [request error]; if (!error) { NSString *response = [request responseString]; NSLog(@"response is : %@",response); } else { NSLog(@"Failed to save to data store: %@", [error localizedDescription]); NSLog(@"%@",[error userInfo]); } } + (BOOL)extractIdentity:(SecIdentityRef *)outIdentity andTrust:(SecTrustRef*)outTrust fromPKCS12Data:(NSData *)inPKCS12Data { OSStatus securityError = errSecSuccess; CFStringRef password = CFSTR("p@ssw0rd888"); //证书密码 const void *keys[] = { kSecImportExportPassphrase }; const void *values[] = { password }; CFDictionaryRef optionsDictionary = CFDictionaryCreate(NULL, keys,values, 1,NULL, NULL); CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL); //securityError = SecPKCS12Import((CFDataRef)inPKCS12Data,(CFDictionaryRef)optionsDictionary,&items); securityError = SecPKCS12Import((CFDataRef)inPKCS12Data,optionsDictionary,&items); if (securityError == 0) { CFDictionaryRef myIdentityAndTrust = CFArrayGetValueAtIndex (items, 0); const void *tempIdentity = NULL; tempIdentity = CFDictionaryGetValue (myIdentityAndTrust, kSecImportItemIdentity); *outIdentity = (SecIdentityRef)tempIdentity; const void *tempTrust = NULL; tempTrust = CFDictionaryGetValue (myIdentityAndTrust, kSecImportItemTrust); *outTrust = (SecTrustRef)tempTrust; } else { NSLog(@"Failed with error code %d",(int)securityError); return NO; } return YES; } @end
在项目中调用 testClientCertificate方法,发现会报以下错误
2014-01-04 15:49:51.194 Mac[661:303] CFNetwork SSLHandshake failed (-9807) 2014-01-04 15:49:51.203 Mac[661:303] Failed to save to data store: A connection failure occurred: SSL problem (Possible causes may include a bad/expired/self-signed certificate, clock set to wrong date) 2014-01-04 15:49:51.204 Mac[661:303] { NSLocalizedDescription = "A connection failure occurred: SSL problem (Possible causes may include a bad/expired/self-signed certificate, clock set to wrong date)"; NSUnderlyingError = "Error Domain=NSOSStatusErrorDomain Code=-9807 \"The operation couldn\U2019t be completed. (OSStatus error -9807.)\" (errSSLXCertChainInvalid: Invalid certificate chain )"; }
怎么会这样?分析最后一句“Invalid certificate chain” 意思是无效的证书链。因为每一个证书中都有一个证书链,来表示这个证书的层次结构。报这个错是因为这个客户端证书的最顶层是我们自己创建的证书,而不是合 法的证书机构颁发的。每个操作系统默认会把一些公认的证书机构颁发的公钥证书存在系统信认的根证书库中,以便信任由这些公认的证书机构签名给其它用户的证 书。那么如何在测试环境中避免这个错?我们只要修改ASIHTTPRequest框架中的相关配置就行了,打开ASIHTTPRequest.m文件,查 找“https”关健字,找到
NSMutableDictionary *sslProperties = [NSMutableDictionary dictionaryWithCapacity:1];
将其注掉,然后换成以下代码
NSMutableDictionary *sslProperties =[[NSMutableDictionary alloc] initWithObjectsAndKeys: [NSNumber numberWithBool:YES], kCFStreamSSLAllowsExpiredCertificates, [NSNumber numberWithBool:YES], kCFStreamSSLAllowsAnyRoot, [NSNumber numberWithBool:NO], kCFStreamSSLValidatesCertificateChain, kCFNull,kCFStreamSSLPeerName, nil];
解决我们的错误的关键代码是
[NSNumber numberWithBool:NO], kCFStreamSSLValidatesCertificateChain 表示不校验证书链。
保存一下再运行就可以正常访问应用了。
有任何问题可以联系我 qq 359709421
相关推荐
通过以上步骤,我们可以有效地利用ASIHttpRequest在iOS应用中实现HTTPS请求,并确保数据传输的安全性。在实际开发中,还应该根据具体需求调整ATS设置,以满足不同场景下的安全需求。同时,定期检查证书的有效性和...
- 同步请求:虽然不推荐在主线程中使用同步请求,因为会阻塞用户界面,但ASIHTTPRequest也支持同步请求,通过`-[ASIHTTPRequest startSynchronous]`方法可以实现。通常在后台线程中使用同步请求。 3. 集成与使用 ...
- **初始化请求**:通过`[ASIHTTPRequest requestWithURL:]`创建一个请求对象,并设置URL。 - **设置请求属性**:如`setShouldUsePipelining:`用于开启HTTP管道,`setShouldContinueWhenAppEntersBackground:`使...
ASIHTTPRequest是iOS开发中早期广泛使用的一个网络请求库,由美国...总之,ASIHTTPRequest是一个经典的网络请求库,它的设计理念和实现方法对于iOS开发者来说,无论是历史回顾还是实际应用,都具有一定的学习价值。
6. **请求队列管理**:可以将多个请求放入请求队列,实现批处理和顺序执行,避免同时发起大量请求导致服务器压力过大。 7. **自定义请求头和请求体**:允许开发者添加自定义的HTTP头和POST数据,适应各种API接口的...
- 可以配置请求使用 HTTPS,`-[ASIHTTPRequest setShouldUseExtendedSSL:]`。 11. **自定义证书**: - 对于自签名的 SSL 证书,可以使用 `-[ASIHTTPRequest setAllowInvalidSSLCertificates:]`。 在提供的 ...
本项目"ASIHttpRequest 队列下载 UITableView实现"旨在教你如何利用ASIHttpRequest库进行队列下载,并通过UITableView来展示下载进度和管理下载任务。 首先,了解ASIHttpRequest库的核心功能。它支持HTTP的各种方法...
3. **请求队列管理**:ASIHTTPRequest提供请求队列,可以将多个请求放入队列中,按顺序执行,避免同时发起过多请求导致的性能问题。 4. **缓存机制**:支持自动缓存响应数据,提高数据获取速度,减少网络带宽使用。...
本项目使用了ASIHTTPRequest库与UITableView相结合来实现这一功能。ASIHTTPRequest是一个广泛使用的HTTP请求库,它提供了简单易用的API,使得网络请求操作变得相对简单。而UITableView则是iOS中用于展示列表数据的...
3. **自动处理Cookie**:ASIHttpRequest会自动管理服务器返回的Cookie,方便下次请求时自动携带,实现了Cookie的持久化。 4. **请求缓存**:支持本地缓存策略,当网络不畅时,可以从本地缓存读取数据,提高了应用的...
2. **初始化请求**:创建ASIHTTPRequest对象,指定URL和请求方法(GET、POST等)。 3. **设置参数**:如果需要发送数据,可以通过setPostValue或setRequestData设置POST参数。 4. **开始请求**:调用start方法启动...
2. **请求队列**:ASIHTTPRequest提供了请求队列,可以同时管理多个网络请求,并按照指定的顺序执行它们,避免了同时处理大量请求时可能出现的问题。 3. **缓存**:ASIHTTPRequest支持HTTP缓存策略,可以自动或手动...
1. **ASIHTTPRequestDelegate**:定义了ASIHTTPRequest代理可能需要实现的方法,如请求完成、失败等回调。 2. **ASIProgressDelegate**:规定了上传和下载进度委托所需实现的方法,用于监听上传和下载进度。 3. **...
6. **请求队列管理**:ASIHTTPRequest支持请求队列,可以方便地管理和控制多个并发请求,避免过度消耗系统资源。 7. **错误处理**:当请求失败时,ASIHTTPRequest会提供详细的错误信息,帮助开发者定位问题所在。 ...
在这个特定的主题中,我们关注的是"ASIHTTPRequest实现资源的下载,断点续传"。断点续传是一项重要的下载技术,尤其在处理大文件或网络不稳定时,它允许用户暂停下载并在稍后继续,而无需重新开始。 首先,了解断点...
1. 异步请求:ASIHTTPRequest 支持异步请求,这意味着在发送请求时,应用程序可以继续执行其他任务,而不会阻塞用户界面。这提高了应用的响应速度和用户体验。 2. 请求队列:ASIHTTPRequest 包含一个请求队列,允许...