経緯
iOSアプリを開発しているとき、WKWebViewでユーザー認証をしたあとにその認証情報(Cookie)を使ってWEBAPIを叩いてユーザーの情報等を把握したいことがあります。
しかしながら、どうやらWKWebViewとWEBAPIを叩く時に標準的に使われるURLSessionではCookieは暗黙的に共有されていないようです。
そこで、URLSessionでWKWebViewのCookieを使用するためにはどのようにしたらいいのかを書いていきます。
もしも、WKWebViewのCookieを使って簡単にWEBAPIを叩く方法がある場合は教えてください!!
流れ
- WKWebViewからCookieを取得する。
- CookieをHTTPヘッダーに埋め込む形に変形させる
- URLSessionでGET(POST)するときにHTTPヘッダーにCookieを追加
WKWebViewからCookieを取得する
特定のドメインに利用されるCookieをWKWebViewから取得します。この工程は先ほどの流れの1と2です。
今回はCookieを常に保持しておきたかったので、UserDefaultsにCookieを保存しています。
var stringCookie:String = ""
webview.configuration.websiteDataStore.httpCookieStore.getAllCookies() {(cookies) in
// [参考]:取得したcookiesは[HTTPCookie]型です。cookiesにはWKWebViewの全ての Cookieが含まれます。
for eachcookie in cookies {
if eachcookie.domain.contains("ドメイン名。ワイルドカードなら `.example.com` 等と入力する"){
stringCookie += "\(eachcookie.name)=\(eachcookie.value);" //HTTPヘッダーの形に変形
}
}
// UserDefaults のインスタンス UserDefaultsに保存するかは自分の使い方に合わせてください
let userDefaults = UserDefaults.standard
// UserDefaults に特定のドメインのCookieを保存。
userDefaults.set(stringCookie,forKey: "stringCookie")
userDefaults.synchronize()
}
これにて特定ドメインのCookieを取得して、HTTPヘッダーに挿入されるフォーマットに変形できます。
この変形後のCookieを使ってWEBAPIを殴ります。
URLSessionを使ってWEBAPIを叩く
先ほどの工程の3にあたります。あとは通常通りWEBAPIを叩く際にHTTPヘッダーにCookieを追加するだけです。
// URL生成
let requestUrl:String = "WEBAPIのURLをここに記述"
guard let url = URL(string: requestUrl) else {
// URL生成失敗
return
}
// リクエスト生成
var request = URLRequest(url: url)
// UserDefaults のインスタンス
let userDefaults = UserDefaults.standard
if let stringCookie = userDefaults.string(forKey: "stringCookie"){
// UserDefaultsからCookieを取得してHTTPヘッダーに追加。
request.setValue(stringCookie, forHTTPHeaderField: "Cookie")
}
let session = URLSession.shared
let task = session.dataTask(with: request) { (data:Data?,response:URLResponse?, error:Error?) in
// 通信完了後の処理
guard let data = data else {
// データなし
return
}
// jsonをそのまま表示
do {
let object = try JSONSerialization.jsonObject(with: data, options: [])
print(object)
} catch let e {
print(e)
}
}
// 通信開始
task.resume()
重要なのは
request.setValue(stringCookie, forHTTPHeaderField: "Cookie")
です。この部分でCookieを付加しています。
このソースコードではJSONのパース等は行なわず、取得したJSONをそのまま表示しています。
JSONをパースする場合はこちらの記事等を参考にするといいと思います。
SwiftでQiitaのAPIを表示させる。
参考
あとがき
もし、こうしたらいいとかあったら教えてください。
この方法はWKWebViewとURLSessionのCookie共有がうまくいかなくて逃避しつつ涙目になりながら考えてました。
そもそも、ネット上ではiOSのWebViewに関しての情報が錯綜している気がします。原因は
- Objective-C と Swiftの情報が混ざっている
- UIWebView と WKWebView の情報が混ざっている。