什么是双向认证呢?简而言之,就是服务器端对请求它的客户端要进行身份验证,客户端对自己所请求的服务器也会做身份验证。服务端一旦验证到请求自己的客户端为不可信任的,服务端就拒绝继续通信。客户端如果发现服务端为不可信任的,那么也中止通信。
双向认证的算法理论是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 表示不校验证书链。
保存一下再运行就可以正常访问应用了。
ASIHTTPRequest实现https双向认证请求的更多相关文章
-
HTTPS 双向认证构建移动设备安全体系
HTTPS 双向认证构建移动设备安全体系 对于一些高安全性要求的企业内项目,我们有时希望能够对客户端进行验证.这个时候我们可以使用Https的双向认证机制来实现这个功能. 单向认证:保证server是 ...
-
httpd设置HTTPS双向认证
去年用tomcat.jboss配置过HTTPS双向认证,那时候主要用的是JDK自带的keytool工具.这次是用httpd + openssl,区别比较大 在网上搜索了很多文章,发现全面介绍的不多,或 ...
-
Android Https双向认证 + GRPC
keywords:android https 双向认证android GRPC https 双向认证 ManagedChannel channel = OkHttpChannelBuilder.for ...
-
nodejs之https双向认证
说在前面 之前我们总结了https的相关知识,如果不懂可以看我另一篇文章:白话理解https 有关证书生成可以参考:自签证书生成 正题 今天使用nodejs来实现https双向认证 话不多说,直接进入 ...
-
SpringBoot服务间使用自签名证书实现https双向认证
SpringBoot服务间使用自签名证书实现https双向认证 以服务server-one和server-two之间使用RestTemplate以https调用为例 一.生成密钥 需要生成server ...
-
Tomcat 配置 HTTPS双向认证
Tomcat 配置 HTTPS 双向认证指引说明: � 本文档仅提供 Linux 操作系统下的指引 � 在阅读本指引前请您在 Linux 部署 JDK 和 Tomcatserver为了 Tomcat ...
-
Https双向认证Android客户端配置
Https .cer证书转换为BKS证书 公式https://blog.csdn.net/zww986736788/article/details/81708967 keytool -importce ...
-
双向认证 HTTPS双向认证
[微信支付]微信小程序支付开发者文档 https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=4_3 HTTPS双向认证使用说明 ...
-
https双向认证訪问管理后台,採用USBKEY进行系统訪问的身份鉴别,KEY的证书长度大于128位,使用USBKEY登录
近期项目需求,须要实现用USBKEY识别用户登录,採用https双向认证訪问管理后台管理界面,期间碰到过一些小问题,写出来给大家參考下. 1:前期准备工作 USBKEY 硬件:我买的是飞天诚信 epa ...
随机推荐
-
windows.open()、close()方法详解
windows.open()方法详解: window.open(URL,name,features,replace)用于载入指定的URL到新的或已存在的窗口中,并返回代表新窗口的Win ...
-
Unity C# 反编译
前言 结合前篇:[反编译U3D]Decompile Unity Resources 修正 本篇说说如何查看unity项目(apk) 的源代码,前提是这个apk的代码未经过加密. 写这篇的目地就是看看别 ...
-
fusioncharts图例(legend)属性
图例用来在多系列图和混合图中将图形和对应的系列名称联系起来. 从v3.2开始,每个系列的名称前面会展示对应的icon图标,这些图标具有交互作用,用户可以通过点击这些图标来显示或者隐藏对应的数 ...
-
MEF(Managed Extensibility Framework )的入门介绍
1.什么是MEF MEF是一个来自于微软协作构建扩展应用的新框架,它的目的是在运行中的应用中添加插件.MEF继承于.NET 4.0 Framework平台,存在于各种应用平台的系统程序集中 2.程序集 ...
-
extjs插件开发上传下载文件简单案例
前台,extjs,框架,mybatis,spring,springMVC,简单的文件上传下载案例. 必要的jar包,commons-fileupload-1.3.1.jar,commons-io-2. ...
-
rsyslog 定义模板
rsyslog默认会将特殊字符(\t)转换成#009 由全局配置$EscapeControlCharactersOnReceive 决定,如果自己需要根据\t处理输出时,需将该选项改为 off. $E ...
-
【C#】聊聊不需要记密码的密码管理补充帖 —— 具体实现
开篇第一句话,就是“小白继续,有实际经验的兄弟们可以洗洗睡了”,因为这个 Lite 版是个实验性的实现,也由于水平原因源码不忍直视,所以如果你坚持看完了,请留下宝贵意见. 以下,干货: 基本模式: 程 ...
-
如何把我的Java程序变成exe文件?
JAVA是一种“跨平台”的语言,拥有“一次编写,处处运行”的特点,让它成为当今IT行业,必不可少的一门编程语言.每一个软件开发完成之后,应该大家都需要打包程序并发送给客户,常见的方式:java程序打成 ...
-
在Java中调用与系统有关的剪切板Clipboard
java从1.5版开始已经能与系统的剪切板很好的交互了. 如果可以在程序中直接调用系统的剪切板来保存“复制”的对象内容,那可以说的比之前的想法好很多. 下面是一个对java.io.File对象进行co ...
-
linux ACL权限
利用这两个指令就可以了: getfacl:获取某個文件的 ACL 设置 setfacl:设置某個文件的 ACL 规范 [root@study ~]# setfacl [-bkRd] [{-m|-x} ...