Alamofire 中的证书固定
Certificate pinning in Alamofire
我正在创建一个 iPad 应用程序来访问 HTTPS 网络服务。我想实施固定,但遇到问题。
这 class 创建了 Alamofire 管理器(主要取自文档):
class NetworkManager {
var manager: Manager?
init() {
let serverTrustPolicies: [String: ServerTrustPolicy] = [
"www.google.co.uk": .PinCertificates(
certificates: ServerTrustPolicy.certificatesInBundle(),
validateCertificateChain: true,
validateHost: true
),
"insecure.expired-apis.com": .DisableEvaluation
]
manager = Alamofire.Manager(
configuration: NSURLSessionConfiguration.defaultSessionConfiguration(),
serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies)
)
}
}
此函数调用:
static let networkManager = NetworkManager()
public static func testPinning() {
networkManager.manager!.request(.GET, "https://www.google.co.uk").response { response in
if response.1 != nil {
print("Success")
print(response.1)
print(response.1?.statusCode)
} else {
print("Error")
print(response.3)
}
}
}
项目中的certificate is saved并显示在'Targets > Build Phases > Copy Bundle Resources'下。
我目前每次发出请求时都会收到以下错误(来自 testPinning()
中的 else 块):
Optional(Error Domain=NSURLErrorDomain Code=-999 "cancelled" UserInfo={NSErrorFailingURLKey=https://www.google.co.uk/, NSLocalizedDescription=cancelled, NSErrorFailingURLStringKey=https://www.google.co.uk/})
所以,问题是证书以错误的格式保存。
ServerTrustPolicy.certificatesInBundle()
根据扩展列表找到捆绑包中的所有证书,然后尝试使用 SecCertificateCreateWithData
加载它们。根据其文档,此函数:
Returns NULL if the data passed in the data parameter is not a valid
DER-encoded X.509 certificate
当您在 Firefox 中导出证书时,您会在文件浏览器的底部看到一个 "format" pop-up。 Select "X.509 Certificate (DER)",为此您应该获得格式正确的证书。
首先,您需要下载证书。最好的办法是在火狐浏览器上下载证书。
步骤 1
转到您的网页/ API 并单击锁定图标以获取证书。
步骤 2
点击查看证书
步骤 3
单击“证书字段”选项卡的第一部分,然后单击“导出”
步骤 4
Select 格式:- DER
步骤 5
将文件拖放到您的 XCode 项目中
步骤 6
在 'Targets > Build Phases > Copy Bundle Resources'
下添加证书
步骤 7
添加网络管理器文件。将 URL 替换为 google.com
import Foundation
import Alamofire
import SwiftyJSON
class MYPNetworkManager {
var Manager: SessionManager?
init() {
let serverTrustPolicies: [String: ServerTrustPolicy] = [
"https://google.com": .pinCertificates(
certificates: ServerTrustPolicy.certificates(),
validateCertificateChain: true,
validateHost: true
),
"insecure.expired-apis.com": .disableEvaluation
]
Manager = SessionManager(
serverTrustPolicyManager: ServerTrustPolicyManager(policies:
serverTrustPolicies)
)
}
}
步骤 8
添加文件以获取会话管理器
import Foundation
import Alamofire
import SwiftyJSON
class APIPinning {
private static let NetworkManager = MYPNetworkManager()
public static func getManager() -> SessionManager {
return NetworkManager.Manager!
}
}
第 9 步
在 Alamofire 上使用这个会话管理器
例如:-
public static func testPinning() {
NetworkManager.Manager!.request("YourURL", method: .get, encoding: URLEncoding.httpBody, headers: MConnect.headersWithToken)
.validate()
.responseJSON { response in
print(response)
switch response.result {
case .success:
if let value = response.result.value {
let json = JSON(value)
print(json)
} else {
}
case .failure:
print("Error")
}
}
}
在 Alamofire 版本 +5 之后发生了很大的变化,我将在此处列出我为证书固定所做的工作。我的目标是 Moya,因为 Moya 是 Alamofire 之上的一层,适用于 Alamofire 的东西应该适用于 Moya。
首先要获取服务器证书,您需要在浏览器中打开它,然后单击锁定图标
然后您需要点击证书,如屏幕截图所示。
之后,您需要将此证书拖到您的桌面或任何下载它的地方,请查看下面的屏幕截图。
然后您需要使用 add file to in Xcode check screenshoot 将它添加到您的项目中。
这是我的 Alamofire 代码:
var session: Session!
class ViewController: UIViewController {
func testPinning() {
let evaluators: [String: ServerTrustEvaluating] = [
"whosebug.com": PublicKeysTrustEvaluator()
]
let manager = ServerTrustManager(evaluators: evaluators)
session = Session(serverTrustManager: manager)
session
.request(" method: .get)
.validate()
.response(completionHandler: { [weak self] response in
switch response.result {
case .success:
print(response.data)
case .failure(let error):
switch error {
case .serverTrustEvaluationFailed(let reason):
// The reason here is a place where you might fine-tune your
// error handling and possibly deduce if it's an actualy MITM
// or just another error, like certificate issue.
//
// In this case, this will show `noRequiredEvaluator` if you try
// testing against a domain not in the evaluators list which is
// the closest I'm willing to setting up a MITM. In production,
// it will most likely be one of the other evaluation errors.
print(reason)
default:
print("default")
}
}
})
}
对于 Moya,您需要将该会话添加到您的 moya 提供商。
let evaluators: [String: ServerTrustEvaluating] = [
"whosebug.com": PublicKeysTrustEvaluator()
]
let manager = ServerTrustManager(evaluators: evaluators)
session = Session(serverTrustManager: manager)
let provider = MoyaProvider<YourWhosebugProvider>(
session: session
)
provider.request(.pluginManger) { response in
switch response {
case .failure(let err):
print(err)
case .success(let response):
print(response)
}
}
我正在创建一个 iPad 应用程序来访问 HTTPS 网络服务。我想实施固定,但遇到问题。
这 class 创建了 Alamofire 管理器(主要取自文档):
class NetworkManager {
var manager: Manager?
init() {
let serverTrustPolicies: [String: ServerTrustPolicy] = [
"www.google.co.uk": .PinCertificates(
certificates: ServerTrustPolicy.certificatesInBundle(),
validateCertificateChain: true,
validateHost: true
),
"insecure.expired-apis.com": .DisableEvaluation
]
manager = Alamofire.Manager(
configuration: NSURLSessionConfiguration.defaultSessionConfiguration(),
serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies)
)
}
}
此函数调用:
static let networkManager = NetworkManager()
public static func testPinning() {
networkManager.manager!.request(.GET, "https://www.google.co.uk").response { response in
if response.1 != nil {
print("Success")
print(response.1)
print(response.1?.statusCode)
} else {
print("Error")
print(response.3)
}
}
}
项目中的certificate is saved并显示在'Targets > Build Phases > Copy Bundle Resources'下。
我目前每次发出请求时都会收到以下错误(来自 testPinning()
中的 else 块):
Optional(Error Domain=NSURLErrorDomain Code=-999 "cancelled" UserInfo={NSErrorFailingURLKey=https://www.google.co.uk/, NSLocalizedDescription=cancelled, NSErrorFailingURLStringKey=https://www.google.co.uk/})
所以,问题是证书以错误的格式保存。
ServerTrustPolicy.certificatesInBundle()
根据扩展列表找到捆绑包中的所有证书,然后尝试使用 SecCertificateCreateWithData
加载它们。根据其文档,此函数:
Returns NULL if the data passed in the data parameter is not a valid DER-encoded X.509 certificate
当您在 Firefox 中导出证书时,您会在文件浏览器的底部看到一个 "format" pop-up。 Select "X.509 Certificate (DER)",为此您应该获得格式正确的证书。
首先,您需要下载证书。最好的办法是在火狐浏览器上下载证书。
步骤 1
转到您的网页/ API 并单击锁定图标以获取证书。
步骤 2
点击查看证书
步骤 3
单击“证书字段”选项卡的第一部分,然后单击“导出”
步骤 4
Select 格式:- DER
步骤 5
将文件拖放到您的 XCode 项目中
步骤 6
在 'Targets > Build Phases > Copy Bundle Resources'
下添加证书步骤 7
添加网络管理器文件。将 URL 替换为 google.com
import Foundation
import Alamofire
import SwiftyJSON
class MYPNetworkManager {
var Manager: SessionManager?
init() {
let serverTrustPolicies: [String: ServerTrustPolicy] = [
"https://google.com": .pinCertificates(
certificates: ServerTrustPolicy.certificates(),
validateCertificateChain: true,
validateHost: true
),
"insecure.expired-apis.com": .disableEvaluation
]
Manager = SessionManager(
serverTrustPolicyManager: ServerTrustPolicyManager(policies:
serverTrustPolicies)
)
}
}
步骤 8
添加文件以获取会话管理器
import Foundation
import Alamofire
import SwiftyJSON
class APIPinning {
private static let NetworkManager = MYPNetworkManager()
public static func getManager() -> SessionManager {
return NetworkManager.Manager!
}
}
第 9 步
在 Alamofire 上使用这个会话管理器 例如:-
public static func testPinning() {
NetworkManager.Manager!.request("YourURL", method: .get, encoding: URLEncoding.httpBody, headers: MConnect.headersWithToken)
.validate()
.responseJSON { response in
print(response)
switch response.result {
case .success:
if let value = response.result.value {
let json = JSON(value)
print(json)
} else {
}
case .failure:
print("Error")
}
}
}
在 Alamofire 版本 +5 之后发生了很大的变化,我将在此处列出我为证书固定所做的工作。我的目标是 Moya,因为 Moya 是 Alamofire 之上的一层,适用于 Alamofire 的东西应该适用于 Moya。
首先要获取服务器证书,您需要在浏览器中打开它,然后单击锁定图标
然后您需要点击证书,如屏幕截图所示。
var session: Session!
class ViewController: UIViewController {
func testPinning() {
let evaluators: [String: ServerTrustEvaluating] = [
"whosebug.com": PublicKeysTrustEvaluator()
]
let manager = ServerTrustManager(evaluators: evaluators)
session = Session(serverTrustManager: manager)
session
.request(" method: .get)
.validate()
.response(completionHandler: { [weak self] response in
switch response.result {
case .success:
print(response.data)
case .failure(let error):
switch error {
case .serverTrustEvaluationFailed(let reason):
// The reason here is a place where you might fine-tune your
// error handling and possibly deduce if it's an actualy MITM
// or just another error, like certificate issue.
//
// In this case, this will show `noRequiredEvaluator` if you try
// testing against a domain not in the evaluators list which is
// the closest I'm willing to setting up a MITM. In production,
// it will most likely be one of the other evaluation errors.
print(reason)
default:
print("default")
}
}
})
}
对于 Moya,您需要将该会话添加到您的 moya 提供商。
let evaluators: [String: ServerTrustEvaluating] = [
"whosebug.com": PublicKeysTrustEvaluator()
]
let manager = ServerTrustManager(evaluators: evaluators)
session = Session(serverTrustManager: manager)
let provider = MoyaProvider<YourWhosebugProvider>(
session: session
)
provider.request(.pluginManger) { response in
switch response {
case .failure(let err):
print(err)
case .success(let response):
print(response)
}
}