(本文代码已升级至Swift3)

一,证书的生成,以及服务器配置
参考我前面写的这篇文章:Tomcat服务器配置https双向认证(使用keytool生成证书)
文章详细介绍了HTTPS,SSL/TLS。还有使用key tool生成自签名证书,Tomcat下https服务的配置。
二,SwiftHTTP使用HTTPS进行网络请求
1,证书导入
前面文章介绍了通过客户端浏览器访问HTTPS服务需,需要安装“mykey.p12”,“tomcat.cer”这两个证书。同样,我们开发的应用中也需要把这两个证书添加进来。
记的同时在 “工程” -> “Build Phases” -> “Copy Bundle Resources” 中添加这两个证书文件。
2,配置Info.plist
由于我们使用的是自签名的证书,而苹果ATS(App Transport Security)只信任知名CA颁发的证书,所以在iOS9下即使是HTTPS请求还是会被ATS拦截。
所以在Info.plist下添加如下配置(iOS8不需要):
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
112
113
114
115
import UIKit
import SwiftHTTP
class ViewController: UIViewController{
     
    overridefunc viewDidLoad() {
        super.viewDidLoad()
         
        do {
            letopt = try HTTP.GET("https://192.168.1.112:8443")
             
            opt.auth = { challengein
                 
                //认证服务器证书
                ifchallenge.protectionSpace.authenticationMethod
                    ==NSURLAuthenticationMethodServerTrust {
                    print("服务端证书认证!")
                     
                    letserverTrust:SecTrust= challenge.protectionSpace.serverTrust!
                    letcertificate = SecTrustGetCertificateAtIndex(serverTrust, 0)!
                    letremoteCertificateData
                        =CFBridgingRetain(SecCertificateCopyData(certificate))!
                    letcerPath = Bundle.main.path(forResource:"tomcat", ofType:"cer")!
                    letcerUrl = URL(fileURLWithPath:cerPath)
                    letlocalCertificateData = try! Data(contentsOf: cerUrl)
                     
                    if(remoteCertificateData.isEqual(localCertificateData)
                        ==true) {
                        letcredential = URLCredential(trust: serverTrust)
                        challenge.sender?.use(credential,for: challenge)
                        returnURLCredential(trust: challenge.protectionSpace.serverTrust!)
                    }else {
                        returnnil
                    }
                }
                //认证客户端证书
                elseif challenge.protectionSpace.authenticationMethod
                    ==NSURLAuthenticationMethodClientCertificate
                {
                    print("客户端证书认证!")
                    //获取客户端证书相关信息
                    letidentityAndTrust:IdentityAndTrust= self.extractIdentity();
                     
                    leturlCredential:URLCredential= URLCredential(
                        identity: identityAndTrust.identityRef,
                        certificates: identityAndTrust.certArrayas? [AnyObject],
                        persistence:URLCredential.Persistence.forSession)
                     
                    returnurlCredential
                }
                // 其它情况(不接受认证)
                else{
                    print("其它情况(不接受认证)")
                    returnnil
                }
            }
             
            opt.start { responsein
                print("访问成功,获取数据如下:")
                print(response.text)
            }
        } catchlet error {
            print("请求失败:  \(error)")
        }
    }
     
    //获取客户端证书相关信息
    funcextractIdentity() -> IdentityAndTrust{
        varidentityAndTrust:IdentityAndTrust!
        varsecurityError:OSStatus= errSecSuccess
         
        letpath: String = Bundle.main.path(forResource:"mykey", ofType:"p12")!
        letPKCS12Data = NSData(contentsOfFile:path)!
        letkey : NSString= kSecImportExportPassphrase asNSString
        letoptions : NSDictionary= [key : "123456"]//客户端证书密码
        //create variable for holding security information
        //var privateKeyRef: SecKeyRef? = nil
         
        varitems : CFArray?
         
        securityError =SecPKCS12Import(PKCS12Data, options, &items)
         
        ifsecurityError == errSecSuccess {
            letcertItems:CFArray= items as CFArray!;
            letcertItemsArray:Array= certItems asArray
            letdict:AnyObject? = certItemsArray.first;
            iflet certEntry:Dictionary= dict as?Dictionary<String,AnyObject> {
                // grab the identity
                letidentityPointer:AnyObject? = certEntry["identity"]
                letsecIdentityRef:SecIdentity= identityPointer as!SecIdentity!
                print("\(identityPointer)  :::: \(secIdentityRef)")
                // grab the trust
                lettrustPointer:AnyObject? = certEntry["trust"]
                lettrustRef:SecTrust= trustPointer as!SecTrust
                print("\(trustPointer)  :::: \(trustRef)")
                // grab the cert
                letchainPointer:AnyObject? = certEntry["chain"]
                identityAndTrust =IdentityAndTrust(identityRef: secIdentityRef,
                                        trust: trustRef, certArray:  chainPointer!)
            }
        }
        returnidentityAndTrust;
    }
     
    overridefunc didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}
//定义一个结构体,存储认证相关信息
structIdentityAndTrust {
    varidentityRef:SecIdentity
    vartrust:SecTrust
    varcertArray: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
100
101
102
103
104
import UIKit
import SwiftHTTP
class ViewController: UIViewController{
     
    //自签名网站地址
    letselfSignedHosts = ["192.168.1.112","www.hangge.com"]
     
    overridefunc viewDidLoad() {
        super.viewDidLoad()
         
        do {
            letopt = try HTTP.GET("https://192.168.1.112:8443")
             
            opt.auth = { challengein
                 
                //认证服务器(这里不使用服务器证书认证,只需地址是我们定义的几个地址即可信任)
                ifchallenge.protectionSpace.authenticationMethod
                    ==NSURLAuthenticationMethodServerTrust
                    &&self.selfSignedHosts.contains(challenge.protectionSpace.host) {
                    print("服务器认证!")
                    letcredential = URLCredential(trust: challenge.protectionSpace.serverTrust!)
                    returncredential
                }
                //认证客户端证书
                elseif challenge.protectionSpace.authenticationMethod
                    ==NSURLAuthenticationMethodClientCertificate
                {
                    print("客户端证书认证!")
                    //获取客户端证书相关信息
                    letidentityAndTrust:IdentityAndTrust= self.extractIdentity();
                     
                    leturlCredential:URLCredential= URLCredential(
                        identity: identityAndTrust.identityRef,
                        certificates: identityAndTrust.certArrayas? [AnyObject],
                        persistence:URLCredential.Persistence.forSession)
                     
                    returnurlCredential
                }
                // 其它情况(不接受认证)
                else{
                    print("其它情况(不接受认证)")
                    returnnil
                }
            }
             
            opt.start { responsein
                print("访问成功,获取数据如下:")
                print(response.text)
            }
        } catchlet error {
            print("请求失败:  \(error)")
        }
    }
     
    //获取客户端证书相关信息
    funcextractIdentity() -> IdentityAndTrust{
        varidentityAndTrust:IdentityAndTrust!
        varsecurityError:OSStatus= errSecSuccess
         
        letpath: String = Bundle.main.path(forResource:"mykey", ofType:"p12")!
        letPKCS12Data = NSData(contentsOfFile:path)!
        letkey : NSString= kSecImportExportPassphrase asNSString
        letoptions : NSDictionary= [key : "123456"]//客户端证书密码
        //create variable for holding security information
        //var privateKeyRef: SecKeyRef? = nil
         
        varitems : CFArray?
         
        securityError =SecPKCS12Import(PKCS12Data, options, &items)
         
        ifsecurityError == errSecSuccess {
            letcertItems:CFArray= items as CFArray!;
            letcertItemsArray:Array= certItems asArray
            letdict:AnyObject? = certItemsArray.first;
            iflet certEntry:Dictionary= dict as?Dictionary<String,AnyObject> {
                // grab the identity
                letidentityPointer:AnyObject? = certEntry["identity"]
                letsecIdentityRef:SecIdentity= identityPointer as!SecIdentity!
                print("\(identityPointer)  :::: \(secIdentityRef)")
                // grab the trust
                lettrustPointer:AnyObject? = certEntry["trust"]
                lettrustRef:SecTrust= trustPointer as!SecTrust
                print("\(trustPointer)  :::: \(trustRef)")
                // grab the cert
                letchainPointer:AnyObject? = certEntry["chain"]
                identityAndTrust =IdentityAndTrust(identityRef: secIdentityRef,
                                        trust: trustRef, certArray:  chainPointer!)
            }
        }
        returnidentityAndTrust;
    }
     
    overridefunc didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}
//定义一个结构体,存储认证相关信息
structIdentityAndTrust {
    varidentityRef:SecIdentity
    vartrust:SecTrust
    varcertArray:AnyObject
}

Swift - 使用SwiftHTTP通过HTTPS进行网络请求,及证书的使用相关推荐

  1. Swift - 使用Alamofire通过HTTPS进行网络请求,及证书的使用

    (本文代码已升级至Swift3) 我原来写过一篇文章介绍如何使用证书通过SSL/TLS方式进行网络请求(Swift - 使用URLSession通过HTTPS进行网络请求,及证书的使用),当时用的是 ...

  2. 深入理解HTTPS及在iOS系统中适配HTTPS类型网络请求(上)

    2019独角兽企业重金招聘Python工程师标准>>> 深入理解HTTPS及在iOS系统中适配HTTPS类型网络请求 一.引言 本篇博客主要讨论如何在客户端与服务端之间进行HTTPS ...

  3. Https的数据请求的证书设置

    对于https的网络请求很多人都比较头疼,不止iOS包括pc端和移动端的很多请求都离不开https CFNetwork SSLHandshake failed (-9806) error = Erro ...

  4. HTTP HTTPS 及网络请求与响应

    HTTP URI的全称为 Uniform Resource Identifier,即统一资源标志符 URL的全称为 Universal Resource Locator,即统一资源定位符 URL是UR ...

  5. [Swift]Alamofire使用嵌套参数进行网络请求遇到的问题

    GitHub: https://github.com/Gamin-fzym/DomainManageDemo 之前封装的网络请求方法,最近发发现有些问题. /// Post请求 /// - Param ...

  6. 使用WeexSDK,网络请求信任证书的问题

    使用0.18.0版本的weexSDK,并且是手动导入的SDK. 在项目中创建一个SDResourceRequest(名字随意)类继承WXResourceRequestHandlerDefaultImp ...

  7. iOS 网络请求劫持

    1.概述: NSURLProtocol是URL loading system 中的一个重要的组成部分,它允许我们对全局的网络请求(基于使用URLRequest)做拦截,可拦截的请求类型有NSURLCo ...

  8. 二、Swift网络请求回来的数据我这样取

    网络请求框架Alamofire 源码地址 Swift 2.3 Alamofire3.0版本支持 iOS 8 Swift 3 Alamofire4.0以上版本支持 iOS 9及以上系统 json数据: ...

  9. Swift 网络请求 Moya+RxSwift

    Swift中优雅的网络请求 官方github // 1.定一个enum enum MyService {xxxxcase showUser(id: Int)xxx }// 2.扩展这个enum,符合 ...

最新文章

  1. R语言配对图可视化:pivot_longer函数将宽格式的数据重塑为长格式并进行数据全连接和左连接(left join)、配对图可视化(根据分类变量的值为散点图上的数据点添加颜色)
  2. 信息化应以电子商务为鉴——企业成长的经济共同体道路
  3. NTU 笔记 6422quiz 复习(1~3节)
  4. kali-linux nat模式下无法联网问题
  5. web压测工具http_load原理分析
  6. 数学--数论--素数
  7. linux屏保配置文件夹,Linux下屏保设置
  8. mysql基础14(关于mysql数据库在没有主键情况下去除重复数据办法)
  9. ORACLE 多版本读一致性
  10. mysql约束类型 A P_sql数据类型与约束总结
  11. Unity3D实践1.1:解决摄像机跟随中的视野遮挡问题
  12. win7升级Internet Explorer 11 先决条件更新
  13. JavaScript实现拖动滑块拼图验证(html5、canvas)
  14. 8051单片机驱动TM1620任意字符循环显示程序(详细注释版)
  15. 春季校园招聘简历投递量已超去年同期;亚太房地产市场现逢低买入良机 | 美通企业日报...
  16. 疯狂Android讲义(一)——第一部分
  17. idou老师教你学Istio11 : 如何用Istio实现流量熔断
  18. 递归解九连环并且打印中间过程
  19. AI最全数据集汇总:语音、歌声、音乐、图片、视频等领域开源数据集链接汇总
  20. 【网络】https单向认证和双向认证

热门文章

  1. Nginx源码分析--数据对齐posix_memalign和memalign函数
  2. 主成分分析(PCA)简介
  3. java简介 ppt 精_《JAVA》5选择结构精篇课件.ppt
  4. python实现单例_Python 实现单例模式
  5. linux命令安装组件,Linux安装各种组件
  6. Java项目:校园外卖点餐系统(java+SSM+JSP+maven+mysql)
  7. android bitmap 转drawable,android Drawable转换成Bitmap失败
  8. php 腾讯云实时音视频,腾讯云视频 -实时音视频学习日志
  9. mysql 前台启动_从Windows命令行启动MySQL
  10. mysql 单选字段_mysql字段类型