この記事の内容
-
NSURLSession
とAlamofire
を使用してネットワークPOST
もしくはGET
リクエストを行う方法について説明します。 - SSL Pinning (SSL証明書の検証を行うためのコード)
サンプルコードが提供されるので、このページをブックマークし、これらのコードをプロジェクトにすばやく追加できます。
どうやってテストをするのか?
アプリケーションがネットワークリクエストを成功させることができるかどうかをテストするためのデバッグオプションはたくさんあります。プロキシ、またはWebフックを使用できます。ここでは、無料のオンラインWebフックツール https://webhook.site/
を使用しました。
サイトにアクセスすると、Webフックリンクが表示されます。そのURLへのリクエストを行うことができ、そしてウェブサイトのインターフェイス上でリクエスト内容を見ることができます。
Alamofire
Alamofire
はネットワーク用のオープンソースのフレームワークです。
GET / POST
func sendRequestRequest() {
// httpリクエストヘッダーを追加する
let headers = [
"Authorization":"Bearer ABCD-EFGH-123-456",
"CatName":"NekoNohe",
]
let httpHeaders = HTTPHeaders(headers)
// リクエストを実行する
AF.request("https://apple.com/", method: .get, headers: httpHeaders)
.validate(statusCode: 200..<300)
//.responseJSON { response in
.responseString { response in
switch response.result {
case .success(let value):
debugPrint("HTTP Response Body: \(response.data)")
case .failure(let error):
print(error.localizedDescription)
}
}
}
ファイルのアップロード (multipartFormData)
func requestWith(image: UIImage){
let url = "https://webhook.site/xxxxxxxxxxxx"
let headers: HTTPHeaders = [
"Content-type": "multipart/form-data"
]
guard let imageData = image.jpegData(compressionQuality: 1.0) else { return }
AF.upload(multipartFormData: { (multipartFormData) in
multipartFormData.append(imageData, withName: "image", fileName: "image.jpg", mimeType: "image/jpeg")
}, to: url, method: .put, headers: headers).responseString { (response) in
switch response.result {
case .success(let result):
print(result)
case .failure(let error):
print(error.localizedDescription)
}
}
}
上記の方式を示す引数は使用対象のウェブサイトが要求する方式に変更する必要があります。一部のウェブサイトでは、POST
方式が必要となる可能性があります。
SSL Pinning (証明書の検証)
SSLピン留めとは
クライアントからサーバーにネットワーク要求を行う場合、クライアントとサーバーの間に第三者が存在する可能性があります。そして、第三者がリクエストを傍受し、独自の証明書を使ってデータを変更する可能性があります。しかし、SSL証明書の有効性を検証し、それらが実際のサーバーに属していることを確認すると、そういった行為を防ぐことができます。
ウェブサイトのSSLサーバ証明書を取得する
Safariブラウザを開き、ウェブサイト(https://apple.com など)にアクセスします。
ロックアイコンをクリックし、ボタンをクリックすると詳細が表示されます。
次に、証明書をアイコンからファインダにドラッグします。
コード
まず、パブリック認証ファイルをプロジェクトに追加する。この例では、ファイル名は www.apple.com.cer
だ。ファイルがプログラミングのターゲットにリンクされていることを確認すること。
Alamofire session
を用意する。
var session: Session!
func getSecureSession() -> Session? {
if let filePath = Bundle.main.path(forResource: "www.apple.com", ofType: "cer"),
let data = try? Data(contentsOf: URL(fileURLWithPath: filePath)),
let certificate = SecCertificateCreateWithData(nil, data as CFData) {
let manager = ServerTrustManager(evaluators:
[
"www.apple.com": PinnedCertificatesTrustEvaluator(certificates: [certificate], acceptSelfSignedCertificates: false, performDefaultValidation: true, validateHost: true)
])
let configuration = URLSessionConfiguration.af.default
return Session(configuration: configuration, serverTrustManager: manager)
}
return nil
}
ここに、ドメイン名とポリシーをマッピングする辞書(ディクショナリ)がある。
"www.apple.com": PinnedCertificatesTrustEvaluator(certificates: [certificate], acceptSelfSignedCertificates: false, performDefaultValidation: true, validateHost: true)
リクエストする。
func sendRequestRequest() {
guard let session = getSecureSession() else { return }
self.session = session
// Perform the request
self.session.request("https://apple.com/", method: .get)
.validate(statusCode: 200..<300)
//.responseJSON { response in
.responseString { response in
switch response.result {
case .success(let value):
debugPrint("HTTP Response Body: \(response.data)")
case .failure(let error):
print(error.localizedDescription)
}
}
}
そうすると、接続しているドメインが www.apple.com
なのであればリクエストが通る。
SSL証明を別のウェブサイトの証明書と置き換え、リクエストエラーが発生することを確認してみるといいだろう。
注
SSLサーバ証明書には有効期限があります。
アプリに保存されているSSLサーバ証明書は、たまに更新する必要があります。
NSURLSession
POST / GET
func sendRequest() {
let sessionConfig = URLSessionConfiguration.default
let session = URLSession(configuration: sessionConfig, delegate: nil, delegateQueue: nil)
//URLを設定する
let urlString = "https://webhook.site/xxxxxxxxxxxx"
guard let URL = URL(string: urlString) else { return }
var request = URLRequest(url: URL)
//リクエストの方式 `(GET, POST)` を設定する
request.httpMethod = "GET"
//OAuth 2 Bearer トークン
request.addValue("Bearer ABCD-EFGH-123-456", forHTTPHeaderField: "Authorization")
//httpリクエストヘッダーを追加する
request.addValue("NekoNohe", forHTTPHeaderField: "CatName")
request.addValue("token=NekoNeko", forHTTPHeaderField: "Cookie")
//httpリクエストボディーを追加する
let JSONdictionary : [String: Any] = [
"name": "axel",
"favorite_animal": "fox"
]
if let postData = try? JSONSerialization.data(withJSONObject: JSONdictionary, options: []) {
request.httpBody = postData
}
//データタスクを定義する
let task = session.dataTask(with: request, completionHandler: { (data: Data?, response: URLResponse?, error: Error?) -> Void in
if (error == nil),
let httpResponse = response as? HTTPURLResponse {
// リクエスト成功
let statusCode = httpResponse.statusCode
// TODO: コードをここに追加する
}
else {
print(error?.localizedDescription)
}
})
task.resume()
session.finishTasksAndInvalidate()
}
その他の
私は以前に Twitter
にコンテンツを投稿するための Swift
& NSURLSession
プログラムを書く方法について記事を書いています。こちらからお読みいただけます。