LoginSignup
1
2

More than 3 years have passed since last update.

WKWebViewでリダイレクト中のCookieを扱う

Posted at

WKWebViewでCookieを扱うことについて

例えば、アプリ内のWebViewからWebページにアクセスした際にログイン状態を維持したい時にはWebView通信時にCookieを乗せることで可能になりますが、UIWebViewからWKWebViewに乗り換えた際にリダイレクトにSet-Cookieがつく場合、次のRequestにCookieが乗らず、正常に通信できない問題があったので、色々試行錯誤した結果を書きました。

リダイレクトにSet-Cookie有(問題のケース)

リダイレクトにSet-Cookieがある場合、次のリクエストにCookieは乗りません。

  1. 302(リダイレクト(Set-Cookie=Hoge1) 302にSet-Cookieされたものは次のリクエストには乗らない
  2. Next Request(Cookie="")

リダイレクトにSet-Cookie無(大丈夫なケース)

リダイレクトにSet-Cookieがない場合には次のリクエストにCookieが乗ります。

  1. 302(リダイレクト)
  2. 200(Set-Cookie=Hoge1)
  3. Next Request(Cookie=Hoge1)

対処

諸々調査検証した結果、WKWebViewのリダイレクト中のSet-Cookieについて、以下のことがわかってきました。

  1. WKWebViewでリダイレクト中のSet-Cookieを正しく処理することはできない
  2. 逆にWebviewで開いているページからの遷移では問題が起きない。

そこで2の部分に注目し、Webにhtmlを配置し、そこを経由することでリダイレクトにSet-Cookieがついても正常に通信できることがわかりました。

redirect.html

こんなのをWebに配置します。

<script>
    var el = document.createElement('a');
    var url = decodeURIComponent(window.location.search.substring(1));
    el.href = url;
    el.click();
</script>

使い方

アプリからは以下のようにredirect.htmlのパラメータに遷移先のURLを指定して使います。

let destUrlStr = "https://hogehoge.com"

var allowedCharacterSet = CharacterSet.alphanumerics
allowedCharacterSet.insert(charactersIn: "-._~")
guard let encodedURLString = destUrlStr.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet) else {
    return nil
}

let request = URLRequest(url: URL(string: "https://example.com/redirect.html?" + encodedURLString))
webView.load(request)

色々試して駄目だったケース

リダイレクトが発生したら次のリクエストにCookieを挿入できればいいのですが、WKWebViewはその手段が用意されていなかったので、なかなか手こずりました。

1. リダイレクトのイベントを捕捉して、次のリクエストにCookieを乗せる

このメソッドはリダイレクトが発生するたびに呼ばれますが、このタイミングではまだResponseを取得できませんでした。

func webView(_ webView: WKWebView, didReceiveServerRedirectForProvisionalNavigation navigation: WKNavigation!) {
    // リダイレクトが発生するたびに呼ばれるが、このタイミングではResponseは取得できない
    print("didReceiveServerRedirectForProvisionalNavigation = \(webView.url)")
}

2. Request直前のイベントを捕捉して、送信する前にCookieを挿入する

このメソッドはリダイレクト含むRequest前に呼ばれるため、以下のようにリダイレクト契機であれば、リクエストし直してCookieを挿入することはできそうですが、リダイレクト契機か判定する方法がないため駄目でした。

func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
    print("navigationAction Request = \(navigationAction.request)")
    if リダイレクト契機か {
        self.loadURL()
        decisionHandler(.cancel)
    } else {
        decisionHandler(.allow)
    }
}

3. WKWebView.loadRequestをハックする

こちらの記事を参考にWKWebView.loadRequestをoverrideして内部でURLSessionを使い、自前で制御してしまう方法ですが、この場合にはWKWebViewDelegateの各種メソッドが呼ばれないため使用しませんでした。

サンプルコード

色々挙動を確認できるようにUIWebView/WKWebViewサンプルアプリを用意しました。
確認する際にはUIWebViewController, WKWebViewControllerのurlを設定ください。

使用したツール

今回、検証する際にCharlesを使用しました。
このツールは通信のモニタリングやRequest/Responseの編集ができたりと多岐にわたってかゆいところに手が届くため非常に使いやすかったです。

参考にした記事

WKWEBVIEW REDIRECT WITH COOKIES
WKWebView. My experience
WKWebViewのコード

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2