Swift - 使用Alamofire通过HTTPS进行网络请求,及证书的使用
我原来写过一篇文章介绍如何使用证书通过SSL/TLS方式进行网络请求(Swift - 使用URLSession通过HTTPS进行网络请求,及证书的使用),当时用的是 URLSession。
本文介绍如何使用 Alamofire 来实现HTTPS网络请求,由于Alamofire就是对URLSession的封装,所以实现起来区别不大。
(如果Alamofire的配置使用不了解的,可以先去看看我原来写的文章:Swift - HTTP网络操作库Alamofire使用详解)


1 2 3 4 5 | < key >NSAppTransportSecurity</ key > < dict > < key >NSAllowsArbitraryLoads</ key > < true /> </ dict > |
3,使用两个证书进行双向验证,以及网络请求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | import UIKit import Alamofire class ViewController : UIViewController { override func viewDidLoad() { super .viewDidLoad() //认证相关设置 let manager = SessionManager . default manager.delegate.sessionDidReceiveChallenge = { session, challenge in //认证服务器证书 if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust { print ( "服务端证书认证!" ) let serverTrust: SecTrust = challenge.protectionSpace.serverTrust! let certificate = SecTrustGetCertificateAtIndex (serverTrust, 0)! let remoteCertificateData = CFBridgingRetain ( SecCertificateCopyData (certificate))! let cerPath = Bundle .main.path(forResource: "tomcat" , ofType: "cer" )! let cerUrl = URL (fileURLWithPath:cerPath) let localCertificateData = try! Data (contentsOf: cerUrl) if (remoteCertificateData.isEqual(localCertificateData) == true ) { let credential = URLCredential (trust: serverTrust) challenge.sender?.use(credential, for : challenge) return ( URLSession . AuthChallengeDisposition .useCredential, URLCredential (trust: challenge.protectionSpace.serverTrust!)) } else { return (.cancelAuthenticationChallenge, nil ) } } //认证客户端证书 else if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodClientCertificate { print ( "客户端证书认证!" ) //获取客户端证书相关信息 let identityAndTrust: IdentityAndTrust = self .extractIdentity(); let urlCredential: URLCredential = URLCredential ( identity: identityAndTrust.identityRef, certificates: identityAndTrust.certArray as ? [ AnyObject ], persistence: URLCredential . Persistence .forSession); return (.useCredential, urlCredential); } // 其它情况(不接受认证) else { print ( "其它情况(不接受认证)" ) return (.cancelAuthenticationChallenge, nil ) } } //数据请求 Alamofire .request( "https://192.168.1.112:8443" ) .responseString { response in print (response) } } //获取客户端证书相关信息 func extractIdentity() -> IdentityAndTrust { var identityAndTrust: IdentityAndTrust ! var securityError: OSStatus = errSecSuccess let path: String = Bundle .main.path(forResource: "mykey" , ofType: "p12" )! let PKCS12Data = NSData (contentsOfFile:path)! let key : NSString = kSecImportExportPassphrase as NSString let options : NSDictionary = [key : "123456" ] //客户端证书密码 //create variable for holding security information //var privateKeyRef: SecKeyRef? = nil var items : CFArray ? securityError = SecPKCS12Import ( PKCS12Data , options, &items) if securityError == errSecSuccess { let certItems: CFArray = items as CFArray !; let certItemsArray: Array = certItems as Array let dict: AnyObject ? = certItemsArray.first; if let certEntry: Dictionary = dict as ? Dictionary < String , AnyObject > { // grab the identity let identityPointer: AnyObject ? = certEntry[ "identity" ]; let secIdentityRef: SecIdentity = identityPointer as ! SecIdentity ! print ( "\(identityPointer) :::: \(secIdentityRef)" ) // grab the trust let trustPointer: AnyObject ? = certEntry[ "trust" ] let trustRef: SecTrust = trustPointer as ! SecTrust print ( "\(trustPointer) :::: \(trustRef)" ) // grab the cert let chainPointer: AnyObject ? = certEntry[ "chain" ] identityAndTrust = IdentityAndTrust (identityRef: secIdentityRef, trust: trustRef, certArray: chainPointer!) } } return identityAndTrust; } override func didReceiveMemoryWarning() { super .didReceiveMemoryWarning() } } //定义一个结构体,存储认证相关信息 struct IdentityAndTrust { var identityRef: SecIdentity var trust: SecTrust var certArray: AnyObject } |

4,只使用一个客户端证书
由于我们使用的是自签名的证书,那么对服务器的认证全由客户端这边判断。也就是说其实使用一个客户端证书“mykey.p12”也是可以的(项目中也只需导入一个证书)。
当对服务器进行验证的时候,判断服务主机地址是否正确,是的话信任即可(代码高亮部分)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | import UIKit import Alamofire class ViewController : UIViewController { //自签名网站地址 let selfSignedHosts = [ "192.168.1.112" , "www.hangge.com" ] override func viewDidLoad() { super .viewDidLoad() //认证相关设置 let manager = SessionManager . default manager.delegate.sessionDidReceiveChallenge = { session, challenge in //认证服务器(这里不使用服务器证书认证,只需地址是我们定义的几个地址即可信任) if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust && self .selfSignedHosts.contains(challenge.protectionSpace.host) { print ( "服务器认证!" ) let credential = URLCredential (trust: challenge.protectionSpace.serverTrust!) return (.useCredential, credential) } //认证客户端证书 else if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodClientCertificate { print ( "客户端证书认证!" ) //获取客户端证书相关信息 let identityAndTrust: IdentityAndTrust = self .extractIdentity(); let urlCredential: URLCredential = URLCredential ( identity: identityAndTrust.identityRef, certificates: identityAndTrust.certArray as ? [ AnyObject ], persistence: URLCredential . Persistence .forSession); return (.useCredential, urlCredential); } // 其它情况(不接受认证) else { print ( "其它情况(不接受认证)" ) return (.cancelAuthenticationChallenge, nil ) } } //数据请求 Alamofire .request( "https://192.168.1.112:8443" ) .responseString { response in print (response) } } //获取客户端证书相关信息 func extractIdentity() -> IdentityAndTrust { var identityAndTrust: IdentityAndTrust ! var securityError: OSStatus = errSecSuccess let path: String = Bundle .main.path(forResource: "mykey" , ofType: "p12" )! let PKCS12Data = NSData (contentsOfFile:path)! let key : NSString = kSecImportExportPassphrase as NSString let options : NSDictionary = [key : "123456" ] //客户端证书密码 //create variable for holding security information //var privateKeyRef: SecKeyRef? = nil var items : CFArray ? securityError = SecPKCS12Import ( PKCS12Data , options, &items) if securityError == errSecSuccess { let certItems: CFArray = items as CFArray !; let certItemsArray: Array = certItems as Array let dict: AnyObject ? = certItemsArray.first; if let certEntry: Dictionary = dict as ? Dictionary < String , AnyObject > { // grab the identity let identityPointer: AnyObject ? = certEntry[ "identity" ]; let secIdentityRef: SecIdentity = identityPointer as ! SecIdentity ! print ( "\(identityPointer) :::: \(secIdentityRef)" ) // grab the trust let trustPointer: AnyObject ? = certEntry[ "trust" ] let trustRef: SecTrust = trustPointer as ! SecTrust print ( "\(trustPointer) :::: \(trustRef)" ) // grab the cert let chainPointer: AnyObject ? = certEntry[ "chain" ] identityAndTrust = IdentityAndTrust (identityRef: secIdentityRef, trust: trustRef, certArray: chainPointer!) } } return identityAndTrust; } override func didReceiveMemoryWarning() { super .didReceiveMemoryWarning() } } //定义一个结构体,存储认证相关信息 struct IdentityAndTrust { var identityRef: SecIdentity var trust: SecTrust var certArray: AnyObject } |
原文出自:www.hangge.com 转载请保留原文链接:http://www.hangge.com/blog/cache/detail_1052.html
相关文章:

gRPC简介及简单使用(C++)
gRPC是一个现代的、开源的、高性能远程过程调用(RPC)框架,可以在任何平台运行。gRPC使客户端和服务器端应用程序能够透明地进行通信,并简化了连接系统的构建。gRPC支持的语言包括C、Ruby、Python、Java、Go等。 gRPC默认使用Google的Protocol Buffers&a…
YC中国被撤,陆奇独立运营个人新品牌「奇绩创坛」
整理 | Jane出品 | AI科技大本营(ID:rgznai100)近日,Y Combinator(以下简称 YC) 发布消息称,YC 将撤回 YC 中国业务与运营,这一品牌也将停止使用,YC的战略布局将调整重新…

shell 脚本逐行读取多个文件,并逐行对应
#!/bin/bashfor i in seq 448doaaased -n "$i"p num.txtbbbsed -n "$i"p text.txt/root/cooper/sms.pl $aaa $bbbdonenum.txt 记录了348个号码text.txt中记录了348个字段效果是取num.txt中第一行作为第一行参数 取text.txt中第一行作为第二个参数num.txt要…

iOS常用知识点1
多线程、特别是NSOperation 和 GCD 的内部原理。 运行时机制的原理和运用场景。 SDWebImage的原理。实现机制。如何解决TableView卡的问题。 block和代理的,通知的区别。block的用法需要注意些什么。 strong,weak,retain,assign&a…
美团BERT的探索和实践 | CSDN原力计划
扫码参与CSDN“原力计划”作者 | 杨扬 佳昊 金刚等来源 | CSDN原力计划作品*点击阅读原文,查看美团技术团队更多干货文章。背景2018年,自然语言处理(Natural Language Processing,NLP)领域最激动人心的进展莫过于预训练…

程序员的自我修养--链接、装载与库笔记:可执行文件的装载与进程
可执行文件只有装载到内存以后才能被CPU执行。 1. 进程虚拟地址空间 程序和进程有什么区别:程序(或者狭义上讲可执行文件)是一个静态的概念,它就是一些预先编译好的指令和数据集合的一个文件;进程则是一个动态的概念,它是程序运…

JDBC实例--工具类升级,使用Apache DBCP连接池重构DBUtility,让连接数据库更有效,更安全...
直接使用JDBC访问数据库时,需要避免以下隐患: 1. 每一次数据操作请求都需要建立数据库连接、打开连接、存取数据和关闭连接等步骤。而建立和打开数据库连接是一件既耗资源又费时的过程,如果频繁发生这种数据库操作,势必会使系统性能下降。 2.…

程序员的自我修养--链接、装载与库笔记:Linux共享库的组织
共享库(Shared Library)概念:其实从文件结构上来讲,共享库和共享对象没什么区别,Linux下的共享库就是普通的ELF共享对象。由于共享对象可以被各个程序之间共享,所以它也就成为了库的很好的存在形式,很多库的开发者都以…

iOS下JS与原生OC互相调用
iOS开发免不了要与UIWebView打交道,然后就要涉及到JS与原生OC交互,今天总结一下JS与原生OC交互的两种方式。 JS调用原生OC篇 方式一 第一种方式是用JS发起一个假的URL请求,然后利用UIWebView的代理方法拦截这次请求,然后再做相…
马斯克发首款会上火星的电动皮卡:28万起,可防弹,造型相当“赛博朋克”...
整理 | Jane、非主流出品 | AI科技大本营(ID:rgznai100)【导读】马斯克今日发布酝酿多年、“真爱系列”的第一辆电动皮卡Cybertruck,Cybertruck 是赛博朋克(cyberpunk)与卡车(truck)…

让你提升命令行效率的 Bash 快捷键
为什么80%的码农都做不了架构师?>>> 原文:http://linuxtoy.org/archives/bash-shortcuts.html 生活在 Bash shell 中,熟记以下快捷键,将极大的提高你的命令行操作效率。 编辑命令 Ctrl a :移到命令行首Ct…

程序员的自我修养--链接、装载与库笔记:Windows下的动态链接
Windows下的PE的动态链接与Linux下的ELF动态链接相比,有很多类似的地方,但也有很多不同的地方。 1. DLL简介 DLL即动态链接库(Dynamic-Link Library)的缩写,它相当于Linux下的共享对象。Windows系统中大量采用了这种DLL机制,甚至…

iOS下JS与OC互相调用(一)--UIWebView 拦截URL
1.在JS 中做一次URL跳转,然后在OC中拦截跳转。(这里分为UIWebView 和 WKWebView两种,去年因为还要兼容iOS 6,所以没办法只能采用UIWebView来做。)2.利用WKWebView 的MessageHandler。3.利用系统库JavaScriptCore&#…
AI换脸鉴别率超99.6%,微软用技术应对虚假信息
来源 | 微软亚洲研究院AI头条(ID:MSRAsia)近日社交网络上爆红的一款换脸应用,让许多普通用户体验到了跟爱豆同框、与偶像飙戏的快乐,也因数据使用带来的问题陷入了舆论的漩涡——除了用户隐私保障,如何辨别和处理换脸应…

使用Apache Tiles3.x构建界面布局(一)
Tiles是一个免费的开源模板Java应用程序的框架。基于复合模式简化的用户界面的构建。对于复杂的网站仍是最简单、最优雅的方式与任何MVC技术一起工作。Struts2对Tiles提供了支持,如今Tiles发展已有13个年头,成为Apache的一个独立项目,我们可以…

iOS下JS与OC互相调用(二)--WKWebView 拦截URL
在上篇文章中讲述了使用UIWebView拦截URL的方式来处理JS与OC交互。 由于UIWebView比较耗内存,性能上不太好,而苹果在iOS 8中推出了WKWebView。 同样的用WKWebView也可以拦截URL,做JS 与OC交互。关于WKWebView与UIWebView的对比,大…
基于模型的强化学习比无模型的强化学习更好?错!
作者 | Carles Gelada and Jacob Buckman编辑 | DeepRL来源 | 深度强化学习实验室(ID:Deep-RL)【导读】许多研究人员认为,基于模型的强化学习(MBRL)比无模型的强化学习(MFRL)具有更高的样本效率。但是&…

程序员的自我修养--链接、装载与库笔记:内存
1. 程序的内存布局 现代的应用程序都运行在一个内存空间里,在32位的系统里,这个内存空间拥有4GB(2的32次方)的寻址能力。应用程序可以直接使用32位的地址进行寻址,这被称为平坦(flat)的内存模型。在平坦的内存模型中,整个内存是一…

【Away3D代码解读】(四):主要模块简介
数据模块: Away3D中最核心的数据类是Mesh类,我们先看看Mesh类的继承关系: NamedAssetBase:为对象提供id和name属性,是Away3D大部分类的基类; Object3D:3D对象基类,提供方便操作3D对象…

程序员的自我修养--链接、装载与库笔记:运行库
1. 入口函数和程序初始化 程序从main开始吗?:操作系统装载程序之后,首先运行的代码并不是main的第一行,而是某些别的代码,这些代码负责准备好main函数执行所需要的环境,并且负责调用main函数,这…

iOS下JS与OC互相调用(三)--MessageHandler
使用WKWebView的时候,如果想要实现JS调用OC方法,除了拦截URL之外,还有一种简单的方式。那就是利用WKWebView的新特性MessageHandler来实现JS调用原生方法。 MessageHandler 是什么? WKWebView 初始化时,有一个参数叫…
北大教授张大庆:无线感知,让你变老也优雅
受访者 | 张大庆记者 | 胡巍巍出品 | CSDN(ID:CSDNnews)在国内高校中,北大的校庆日很特殊——5月4日。这一天,也是青年节。北大,是五四运动的策源地。100年来,“爱国、进步、民主、科学”的五四…

总结 20 个开发细节
2019独角兽企业重金招聘Python工程师标准>>> 1:提交到SVN的代码必须有提交备注,以便于以后查看。 2:如考虑页面缓存,可以在路径后增加随机数:url "&TimeS" Math.random();。 3:…

程序员的自我修养--链接、装载与库笔记:系统调用与API
系统调用(System Call)是应用程序(运行库也是应用程序的一部分)与操作系统内核之间的接口,它决定了应用程序是如何与内核打交道的。无论程序是直接进行系统调用,还是通过运行库,最终还是会到达系统调用这个层面上。 1. 系统调用介绍 什么是…

iOS下JS与OC互相调用(四)--JavaScriptCore
前面讲完拦截URL的方式实现JS与OC互相调用,终于到JavaScriptCore了。它是从iOS7开始加入的,用 Objective-C 把 WebKit 的 JavaScript 引擎封装了一下,提供了简单快捷的方式与JavaScript交互。 关于JavaScriptCore的使用有两篇很好的文章&…
围巾都这么黑科技了,是我见识少了
有一个永恒的话题:北方冷一点还是南方冷一点?答案是:哪里都冷!冬天最痛苦的莫过于走出空调房——刺骨的风直直的从领口处灌进去那叫一个“透心凉,心飞扬”缠了好几圈的大围巾却根本没什么保暖效果每当这时候࿰…

【教程】【FLEX】#004 反射机制
总结: 目前用到反射的主要有两个方法 1. getDefinitionByName //根据类名,返回对象(反射实例化对象) 2. describeType //根据对象,返回XML格式的属性,方法等信息(反射得到…

iOS下JS与OC互相调用(五)--UIWebView + WebViewJavascriptBridge
WebViewJavascriptBridge是一个有点年代的JS与OC交互的库,使用该库的著名应用还挺多的,目前这个库有7000star。我去翻看了它的第一版本已经是4年前了,在版本V4.1.4以及之前,该库只有一个类和一个js 的txt文件,所以旧版…

OpenCV代码提取:Windows上通过DShow获取Camera视频
在OpenCV 3.1中获取视频的模块在videoio(video input and output module)中,调用VideoCapture类接口,除了videoio模块外还依赖core、highgui、imgproc、imgcodecs四个模块,而OpenCV 2.4.13.6仅需要core、highgui、imgproc三个模块。3.1中的vi…
迁移学习与图神经网络“合力”模型:用DoT-GNN克服组重识别难题
作者 | Ziling Huang、Zheng Wang、Wei Hu、Chia-Wen Lin、Shin’ichi Satoh译者 | 刘畅编辑 | Jane出品 | AI科技大本营(ID:rgznai100)【导读】目前,大多数行人重识别(ReID)方法主要是从收集的单个人图像数…