我正在创建一个访问HTTPS Web服务的iPad应用程序。我想实现固定,但我遇到了问题。
这个类创建了Alamofire Manager(主要来自文档):
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并显示在'目标>下构建阶段>复制捆绑资源'。
我每次发出请求时都会收到以下错误(来自testPinning()
中的else块):
Optional(Error Domain=NSURLErrorDomain Code=-999 "cancelled" UserInfo={NSErrorFailingURLKey=https://www.google.co.uk/, NSLocalizedDescription=cancelled, NSErrorFailingURLStringKey=https://www.google.co.uk/})
答案 0 :(得分:8)
因此,问题是证书以错误的格式保存。
ServerTrustPolicy.certificatesInBundle()
根据扩展列表查找捆绑包中的所有证书,然后尝试使用SecCertificateCreateWithData
加载它们。根据其文档,此功能:
如果data参数中传递的数据无效,则返回NULL DER编码的X.509证书
在Firefox中导出证书时,您的格式为""弹出文件浏览器的底部。选择" X.509证书(DER)",您应该为此目的获得正确格式的证书。
答案 1 :(得分:1)
在 Alamofire 版本 +5 之后发生了很大的变化,我将在这里列出我为进行证书固定所做的工作。我的目标是 Moya,因为 Moya 作为 Alamofire 之上的层,适用于 Alamofire 的东西应该适用于 Moya。
首先要获得服务器证书,您需要在浏览器中打开它,然后单击锁定图标 然后您需要单击证书,如屏幕截图所示。 之后,您需要将此证书拖到您的桌面或下载它的任何地方,请查看下面的屏幕截图。 然后您需要使用添加文件到 Xcode 检查屏幕截图将其添加到您的项目中。 这是我的 Alamofire 代码:
var session: Session!
class ViewController: UIViewController {
func testPinning() {
let evaluators: [String: ServerTrustEvaluating] = [
"stackoverflow.com": PublicKeysTrustEvaluator()
]
let manager = ServerTrustManager(evaluators: evaluators)
session = Session(serverTrustManager: manager)
session
.request("https://stackoverflow.com/questions/34611112/certificate-pinning-in-alamofire/55902588#55902588", 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] = [
"stackoverflow.com": PublicKeysTrustEvaluator()
]
let manager = ServerTrustManager(evaluators: evaluators)
session = Session(serverTrustManager: manager)
let provider = MoyaProvider<YourStackOVerflowProvider>(
session: session
)
provider.request(.pluginManger) { response in
switch response {
case .failure(let err):
print(err)
case .success(let response):
print(response)
}
}
答案 2 :(得分:0)
首先,您需要下载证书。最好的方法是在Firefox浏览器上下载证书。
第1步
转到您的网页/ API,然后单击锁图标以获取证书。
第2步
点击查看证书
第3步
点击“证书字段”标签的第一部分,然后点击导出
第4步
选择格式:-DER
第5步
将文件拖放到XCode项目中
步骤6
在“目标>构建阶段>复制捆绑包资源”下添加证书
第7步
添加网络管理器文件。将您的网址替换为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")
}
}
}