单项认证:客户端APP包里保存一份证书 用于校验服务端证书是否合法

双向认证:单项认证以外,   客户端(不是app,这里指系统)要拥有一份证书 用于传给服务端用于校验客户端证书是否合法

分两方面讲解:一 客户端配置  二 服务端配置

一 客户端配置。

单向认证流程:

  1. 客户端向服务端发送SSL协议版本号、加密算法种类、随机数等信息。
  2. 服务端给客户端返回SSL协议版本号、加密算法种类、随机数等信息,同时也返回服务器端的证书,即公钥证书
  3. 客户端使用服务端返回的信息验证服务器的合法性,包括:
    • 证书是否过期
    • 发形服务器证书的CA是否可靠
    • 返回的公钥是否能正确解开返回证书中的数字签名
    • 服务器证书上的域名是否和服务器的实际域名相匹配
  4. 验证通过后,将继续进行通信,否则,终止通信
  5. 客户端向服务端发送自己所能支持的对称加密方案,供服务器端进行选择
  6. 服务器端在客户端提供的加密方案中选择加密程度最高的加密方式。
  7. 服务器将选择好的加密方案通过明文方式返回给客户端
  8. 客户端接收到服务端返回的加密方式后,使用该加密方式生成产生随机码,用作通信过程中对称加密的密钥,使用服务端返回的公钥进行加密,将加密后的随机码发送至服务器
  9. 服务器收到客户端返回的加密信息后,使用自己的私钥进行解密,获取对称加密密钥。在接下来的会话中,服务器和客户端将会使用该密码进行对称加密,保证通信过程中信息的安全。

双向认证流程:

  1. 客户端向服务端发送SSL协议版本号、加密算法种类、随机数等信息。
  2. 服务端给客户端返回SSL协议版本号、加密算法种类、随机数等信息,同时也返回服务器端的证书,即公钥证书
  3. 客户端使用服务端返回的信息验证服务器的合法性,包括:
    • 证书是否过期
    • 发形服务器证书的CA是否可靠
    • 返回的公钥是否能正确解开返回证书中的数字签名
    • 服务器证书上的域名是否和服务器的实际域名相匹配
  4. 验证通过后,将继续进行通信,否则,终止通信
  5. 服务端要求客户端发送客户端的证书,客户端会将自己的证书发送至服务端
  6. 验证客户端的证书,通过验证后,会获得客户端的公钥
  7. 客户端向服务端发送自己所能支持的对称加密方案,供服务器端进行选择
  8. 服务器端在客户端提供的加密方案中选择加密程度最高的加密方式
  9. 将加密方案通过使用之前获取到的公钥进行加密,返回给客户端
  10. 客户端收到服务端返回的加密方案密文后,使用自己的私钥进行解密,获取具体加密方式,而后,产生该加密方式的随机码,用作加密过程中的密钥,使用之前从服务端证书中获取到的公钥进行加密后,发送给服务端
  11. 服务端收到客户端发送的消息后,使用自己的私钥进行解密,获取对称加密的密钥,在接下来的会话中,服务器和客户端将会使用该密码进行对称加密,保证通信过程中信息的安全。

是单向认证还是双向认证主要看服务器的配置,与客户端无关。如果是双向认证,服务器在配置的时候必须设置clientAuth=“true”,单向则设置为false,默认值为false。
单向认证需要服务器的公钥证书,我们后台提供给我的server.cer,在网上看到有说AF 3.0之后需要用.der格式的,我用了.cer格式也没有问题。
双向认证不仅需要服务器的公钥证书还需要提供客户端证书,一般为.p12格式而且是带有密码的。

下面直接上代码(单向认证和双向认证适用同一套代码,只要证书配置的对就可以):

AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];//    设置超时时间[manager.requestSerializer willChangeValueForKey:@"timeoutInterval"];manager.requestSerializer.timeoutInterval = 30.f;[manager.requestSerializer didChangeValueForKey:@"timeoutInterval"];[manager.requestSerializer setValue:@"Content-Type" forHTTPHeaderField:@"application/json; charset=utf-8"];[manager setSecurityPolicy:[self customSecurityPolicy]];[self checkCredential:manager];[manager POST:@"这里填你的https地址" parameters:nil progress:^(NSProgress * _Nonnull uploadProgress) {NSLog(@"123");} success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {NSLog(@"成功:%@",responseObject);} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {NSLog(@"失败:%@",error);}];
- (AFSecurityPolicy*)customSecurityPolicy {AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];//获取证书路径NSString * cerPath = [[NSBundle mainBundle] pathForResource:@"server" ofType:@"cer"];NSData *certData = [NSData dataWithContentsOfFile:cerPath];NSSet  *dataSet = [NSSet setWithArray:@[certData]];[securityPolicy setAllowInvalidCertificates:YES];//是否允许使用自签名证书[securityPolicy setPinnedCertificates:dataSet];//设置去匹配服务端证书验证的证书[securityPolicy setValidatesDomainName:NO];//是否需要验证域名,默认YESreturn securityPolicy;
}
//校验证书
- (void)checkCredential:(AFURLSessionManager *)manager
{[manager setSessionDidBecomeInvalidBlock:^(NSURLSession * _Nonnull session, NSError * _Nonnull error) {}];__weak typeof(manager)weakManager = manager;[manager setSessionDidReceiveAuthenticationChallengeBlock:^NSURLSessionAuthChallengeDisposition(NSURLSession*session, NSURLAuthenticationChallenge *challenge, NSURLCredential *__autoreleasing*_credential) {NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;__autoreleasing NSURLCredential *credential =nil;NSLog(@"authenticationMethod=%@",challenge.protectionSpace.authenticationMethod);//判断服务器要求客户端的接收认证挑战方式,如果是NSURLAuthenticationMethodServerTrust则表示去检验服务端证书是否合法,NSURLAuthenticationMethodClientCertificate则表示需要将客户端证书发送到服务端进行检验if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {// 基于客户端的安全策略来决定是否信任该服务器,不信任的话,也就没必要响应挑战if([weakManager.securityPolicy evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:challenge.protectionSpace.host]) {// 创建挑战证书(注:挑战方式为UseCredential和PerformDefaultHandling都需要新建挑战证书)credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];// 确定挑战的方式if (credential) {//证书挑战  设计policy,none,则跑到这里disposition = NSURLSessionAuthChallengeUseCredential;} else {disposition = NSURLSessionAuthChallengePerformDefaultHandling;}} else {disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;}} else { //只有双向认证才会走这里// client authenticationSecIdentityRef identity = NULL;SecTrustRef trust = NULL;NSString *p12 = [[NSBundle mainBundle] pathForResource:@"client"ofType:@"p12"];NSFileManager *fileManager =[NSFileManager defaultManager];if(![fileManager fileExistsAtPath:p12]){NSLog(@"client.p12:not exist");}else{NSData *PKCS12Data = [NSData dataWithContentsOfFile:p12];if ([self extractIdentity:&identity andTrust:&trust fromPKCS12Data:PKCS12Data]){SecCertificateRef certificate = NULL;SecIdentityCopyCertificate(identity, &certificate);const void*certs[] = {certificate};CFArrayRef certArray =CFArrayCreate(kCFAllocatorDefault, certs,1,NULL);credential =[NSURLCredential credentialWithIdentity:identity certificates:(__bridge  NSArray*)certArray persistence:NSURLCredentialPersistencePermanent];disposition =NSURLSessionAuthChallengeUseCredential;}}}*_credential = credential;return disposition;}];
}
//读取p12文件中的密码
- (BOOL)extractIdentity:(SecIdentityRef*)outIdentity andTrust:(SecTrustRef *)outTrust fromPKCS12Data:(NSData *)inPKCS12Data {OSStatus securityError = errSecSuccess;//client certificate passwordNSDictionary*optionsDictionary = [NSDictionary dictionaryWithObject:@"123456"forKey:(__bridge id)kSecImportExportPassphrase];CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);securityError = SecPKCS12Import((__bridge CFDataRef)inPKCS12Data,(__bridge CFDictionaryRef)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(@"Failedwith error code %d",(int)securityError);return NO;}return YES;
}

下面看一下服务端配置

二   服务端配置

服务端环境 :httpd: 2.4.4  openssl:1.0.1  os:ubuntu 12.04 LTS

首先,修改httpd.conf文件,加载必要的模块

  1. LoadModule socache_shmcb_module modules/mod_socache_shmcb.so
  2. LoadModule socache_dbm_module modules/mod_socache_dbm.so
  3. LoadModule socache_memcache_module modules/mod_socache_memcache.so
  4. LoadModule ssl_module modules/mod_ssl.so

然后再导入默认的SSL配置文件,当然也可以选择不导入,在httpd.conf直接配置。但是导入默认的可以节省很多时间,并且默认的文件是用vhost配置的,不会跟main server冲突,可以算是一种最佳实践

  1. # Secure (SSL/TLS) connections
  2. Include conf/extra/httpd-ssl.conf
  3. <IfModule ssl_module>
  4. SSLRandomSeed startup builtin
  5. SSLRandomSeed connect builtin
  6. </IfModule>

然后打开httpd-ssl.conf,主要有以下几个配置

  1. SSLEngine on
  2. SSLCertificateFile "/usr/local/httpd/conf/server.cer"
  3. SSLCertificateKeyFile "/usr/local/httpd/conf/server.key.pem"
  4. #SSLCACertificateFile "/usr/local/httpd/conf/ca.cer"
  5. #SSLVerifyClient require
  6. #SSLVerifyDepth  10

只要开启前3个,单向的HTTPS认证就配置好了。后面3个目前先注释掉,是后面双向认证才用到

SSLCACertificateFile,这个意思是当客户端发来客户端证书的时候,httpd用哪个CA根证书校验它

九、签发客户端证书

1、创建客户端私钥

Openssl代码  
  1. openssl genrsa -aes256 -out private/client.key.pem 2048

2、创建客户端证书签发请求

Openssl代码  
  1. openssl req -new -key private/client.key.pem -out private/client.csr -subj "/C=CN/ST=SZ/L=SZ/O=kyfxbl/OU=kyfxbl/CN=kyfxbl"

这里的不同在于,这里的CN不是*.kyfxbl.net,也不是www.kyfxbl.net,随便填一个kyfxbl就好了,或者干脆叫user都没问题,反正是一个客户端证书

3、利用CA根证书,签发客户端证书

Openssl代码  
  1. openssl x509 -req -days 3650 -sha1 -extensions v3_req -CA certificates/ca.cer -CAkey private/ca.key.pem -CAserial ca.srl -CAcreateserial -in private/client.csr -out certificates/client.cer

这里和签发server.cer基本是一样的

4、把客户端证书转换成p12格式

Openssl代码  
  1. openssl pkcs12 -export -clcerts -inkey private/client.key.pem -in certificates/client.cer -out certificates/client.p12

这步是必须的,因为稍后就需要把客户端证书导入到浏览器里,但是一般浏览器都不能直接使用PEM编码的证书

最后导出p12的方法 根据不同的证书 导出p12也不一样 要以实际为准

最后 把p12文件安装在客户端 就可以实现双向认证了

ios https 单项认证 双向认证 以及服务端配置相关推荐

  1. 数据和安全②HTTPS单向和双向认证

    前言 示例 使用SpringBoot模拟服务端和客户端,使用okhttp作为httpClient工具. 如果对https相关理论不太熟悉和理解的可以看上一篇数据和安全①加解密理论概述 Okhttp h ...

  2. 数字证书原理详细介绍 单向认证 双向认证

    证书:就是为了证明自己身份的东西,所以证书要提供给需要校验我们身份的人:一般情况下,客户端需要校验服务端有没有被人伪造,所以客户端需要安装对应的服务端的证书:证书的实质内容就是一把公钥 这里面主要有三 ...

  3. 锐捷路由器CHAP 单向认证 双向认证

    单向认证 R1为认证客户端 进入Router1 进入Serial 2/0接口 interface Serial 2/0 封装PPP协议 encapsulation ppp 启用CHAP认证 ppp a ...

  4. 一篇文章带你了解https是如何做到客户端与服务端之间安全通信

    https是什么. 超文本传输安全协议(英语:Hypertext Transfer Protocol Secure,缩写:HTTPS,常称为HTTP over TLS,HTTP over SSL或HT ...

  5. Java IOS客户端上传多张图片到服务端

    Java IOS客户端上传多张图片到服务端 业务场景:用户相册需要上传多张图片到服务器,上限为12张.本文主要介绍Java服务端的文件和流的处理. 下图为iOS端和服务端最终结果一览.  iOS端 : ...

  6. 1.Ubuntu16.04-NTP服务端配置

    NTP服务端配置 安装ntp软件包 sudo apt-get install ntp 配置ntp服务器 sudo vim /etc/ntp.conf 1.上层主机设定 上层主机选择ntp.aliyun ...

  7. OSSEC服务端配置客户端批量部署方案

    0x00 前言 最近也在研究ossec报警规则,还没研究的很透彻,暂时不是这篇文章的内容.ossec中文资料还是比较少,外文文献比较多.之前看到drops的两篇文章分享/tips/?id=2821,/ ...

  8. NFS介绍、NFS服务端配置安装配置、 NFS配置选项、 客户端的配置

    NFS介绍 NFS是Network File System的缩写 ,是在网络层面,NFS(Network File System)网络文件系统会经常用到,用于在网络上共享存储.这样讲,你对NFS可能不 ...

  9. Linux centos7安装nfs及服务端配置

    安装 [root@hygon-vm ~]# rpm -qa nfs-utils [root@hygon-vm ~]# rpm -qa rpcbind [root@hygon-vm ~]# [root@ ...

最新文章

  1. 『TensorFlow』函数查询列表_张量属性调整
  2. Markdown基本语法【转】
  3. 【IT资讯】MATLAB 不能用了,哪些替代品可以继续搞科研?
  4. linux收缩java位置,找到linux中当前java的安装位置
  5. 2014 网选 5007 Post Robot(暴力或者AC_自动机(有点小题大作了))
  6. Swagger如何测试Date类型参数
  7. 新年寄语 | 2018 以及 Oracle 18c 一个时代的开启
  8. python快速入门教程-终于理解python快速入门教程
  9. KL 散度(从动力系统到推荐系统)
  10. HDU 2674 N!Again
  11. 6款令人相见恨晚的在线搜索网站,成年后都会要用上,了解一下!
  12. 利用R语言进行具有周期性的时间序列分析
  13. mysql中美元符号_Mybatis中#号和美元符号$符号的区别
  14. rust相框加载图片代码_vue图片加载与显示默认图片实例代码
  15. numpy 相关函数
  16. 超实用!网站导航栏设计方法总结
  17. 前端,通过面试去学习,开放问题(个人对前端发展的理解、项目难点、项目亮点、最复杂的逻辑、团队协作冲突问题、HR面试问题)
  18. mysql数据库:varchar类型可以存储多少个汉字,多少个数字
  19. 《C/C++ 面试 100 例》(十一)标准输入加速
  20. 向无所不能逼近的算法 逻辑与算法之一

热门文章

  1. 基于51单片机的人体红外震动检测家庭防盗报警器
  2. 微信环境中APK下载方案 安卓调用默认浏览器打开 IOS跳转App Store(苹果商店)打开
  3. SaltStack之salt-master高可用
  4. 火眼金睛,看透Spring处理Import注解的全过程
  5. Java对于数据加密与解密的实现EncryptUtil、MD5与sha-1
  6. gpu 测试 linux,如何在Linux上对GPU进行基准测试
  7. 电竞蓝牙耳机哪个牌子好?无延迟游戏蓝牙耳机
  8. 【总结】1059- 图解常见的九种设计模式
  9. AutoCAD二次开发——Cad弹出对话框
  10. 闪存数据库概念与技术