コムセント 技術情報

  1. TOP
  2. コムセント 技術情報
  3. SwiftのURLSessionでCookieを取得しWebViewに渡す方法

SwiftのURLSessionでCookieを取得しWebViewに渡す方法

いろいろな言語のプロジェクトに携わっていることもあり、たまに言語の違いで混乱することがあるSekiguchiです。なんで、このメソッドが使えないんじゃ~~!?とか思っていたら違う言語の機能だったり。

皆さまはどうやって複数言語を使い分けてますか??

さて、SwiftでのiOS開発で、どうしたものかと思ったところに触れたので、備忘録を兼ねつつご紹介。
Swiftでサーバーとの通信は、URLSessionを使って取得するのが定番かと思いますが、今回携わったプロジェクトでは、認証時のみNativeのコードでURLSessionを利用し、以降はWKWebViewを使う、という構成でした。この場合、WKWebViewでは認証したときの情報がセッション情報として必要になり、これは認証時にCookieデータとして送られてきます。

つまり、Nativeで受け取ったCookieのデータをWKWebViewでも使いたい、と言うことになるのですが、現状のSwiftでは自動的にCookieデータを共有する機能はありません。
なので、URLSessionで何とかする必要があるのですが、イマイチ明確な情報が無かったので、まとめておきます。Swiftは5.3を利用しています。

Cookieは通常、HTTPヘッダー内にSet-Cookieというヘッダーとともに送られてくるので、この値を取りだしてあげればOKなのですが、URLSessionの場合、レスポンスとして送られてくるデータにこのデータは含まれていません。

request.httpMethod = "POST"
request.timeoutInterval = 10
request.httpBody = postString.data(using: .utf8)
let task = session.dataTask(with: request, completionHandler: {(data,response,error) in
のときにresponseに入ってこない

となると、Cookieはどこにいったのか、となりますが、どうもURLSessionはCookieが含まれていた場合、自動的に格納して処理するようになっているようです。そのため、Cookieデータを参照することが容易にできないようになってしまっています。

CookieはHTTPCookieStorageに格納される

CookieはHTTPCookieStorage.sharedに格納されるため、このオブジェクトを参照し、Cookieデータを取り出します。

let cookieStorage = HTTPCookieStorage.shared
let cookies = cookieStorage.cookies as! [HTTPCookie]//Cookieデータを取得

cookiesの中にCookieのデータが入ってくるのですが、必要なデータだけを取り出します。

for cookie in cookies {
if(cookie.domain == domain){//ドメインが指定したものだった場合
UserDefaults.standard.set(cookie.name,forKey:"cookiename")
UserDefaults.standard.set(cookie.value,forKey:"cookievalue")
}
}

今回は、nameプロパティとvalueプロパティの値を取得し、cookiename、cookievalueという名前でそれぞれUserDefaultsに保存しています。
これで、URLSessionからCookieデータを取り出すことができました。

WKWebViewに対してCookieを適用

あとはWKWebViewに対して、取得したCookieを適用します。

var config:WKWebViewConfiguration!
var mainwebview:WKWebView!
config = WKWebViewConfiguration()
mainwebview = WKWebView(frame: view.frame,configuration: config)
view.addSubview(mainwebview)

デフォルトのWKWebViewConfiguration()を通してcongigをWKWebViewに適用します。
これだと、Cookieデータが適用されていない状態のWKWebViewになるので、先ほど取得したCookieデータを適用します。

let cookie = HTTPCookie(properties: [
HTTPCookiePropertyKey.name:UserDefaults.standard.string(forKey: "cookiename")!,
HTTPCookiePropertyKey.value:UserDefaults.standard.string(forKey: "cookievalue")!,
HTTPCookiePropertyKey.domain:domain,
HTTPCookiePropertyKey.path:"/"
])!
let url = URL(string:"http://example.com")
config.websiteDataStore.httpCookieStore.setCookie(cookie){
[weak self] in
guard let self = self else { return }
self.mainwebview.load(URLRequest(url: self.url!))
}

UserDefaultsに格納したCookieデータを取り出します。最低限、cookie名と値があればOKですが、利用するドメインを指定する必要があるため、Cookieを送出してきたサーバーのドメイン名をdomain(もしhttp://example.comのサーバーから送られてきているなら、example.comがドメイン)として適用します(ここではdomainという変数にドメイン名を格納していて、それを適用しています。)

pathは"/"で、問題無いと思いますが、状況によって変更します。これで最低限のCookieデータが作成できたので、WKWebviewが外部サイトを参照するときに作成したCookieを適用します。

一度CookieデータをWKWebViewに適用すれば、WKWebViewを破壊するまでは生き続けます。
これで、NativeからWKWebViewに対してCookieデータを渡すことができました。

URLSessionはCookieなどを意識せずに処理してくれるので、便利なのですが、ちょっと変わったことをするときは工夫が必要ですね。

おすすめ記事