77
59

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

WKWebViewでのSessionの共有

Last updated at Posted at 2018-03-17

概要

WkWebViewを使ったWebViewアプリでSession情報を共有するための方法をメモ

WKWebView間でSessionの共有

WKWebView 間でSessionを共有するためには WKProcessPool を使います
要注意なのはこの WKProcessPool のインスタンスの共有の仕方で、 必ず WKProcessPool を設定した WKWebViewConfiguration のインスタンスを WKWebView の初期化の際に渡すようにする必要があります
WKWebView を初期化した後に、 WKWebViewConfiguration のsetter経由で設定してもSessionは共有されないようです

◯ Sessionが共有される

let configuration = WKWebViewConfiguration()
let processPool = WKProcessPool()
configuration.processPool = processPool
let webView = WKWebView(frame: .zero, configuration: configuration)

×Sessionが共有されない

let configuration = WKWebViewConfiguration()
let processPool = WKProcessPool()
let webView = WKWebView(frame: .zero, configuration: configuration)
webView.configuration.processPool = processPool

WKProcessPool のインスタンスはアプリケーション内で共有する必要があるため、staticにして保持することをおすすめします。

次回起動時もSessionを共有する

HTTPCookieStrageWKProcessPool のセッション情報は非同期で共有されてしまうため、
同期的にSession情報を扱うためには、

  1. 初回リクエスト時のHTTP Response HeaderのSet-Cookieの値を保存する
  2. 次回起動時にSession情報を引き継ぐ

をする必要があります

1. 初回リクエスト時のHTTP Response HeaderのSet-Cookieの値を保存する

Set-Cookieで渡されるCookie情報を保存するには、webView(_:decidePolicyFor:decisionHandler:)navigationResponse にリクエストしたサーバーからCookieが渡された時に UserDefault 等に保存すればよいかと思います

func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
    if let urlResponse = navigationResponse.response as? HTTPURLResponse,
      let url = urlResponse.url,
      let allHeaderFields = urlResponse.allHeaderFields as? [String : String] {
      let cookies = HTTPCookie.cookies(withResponseHeaderFields: allHeaderFields, for: url)
      for cookie in cookies {
        if cookie.domain == "リクエストしたサーバーのドメイン"  {
          // UserDefaultにCookie情報を保存する
        }
      }
    }
    decisionHandler(.allow)
  }

2.次回起動時にSession情報を引き継ぐ

アプリケーションを終了し、次回起動時にSession情報を引き継いでリクエストするためには、

a. WkWebView の初期化時に document.cookie_session_id を設定する
b. WkWebVie の初回リクエスト時にCookie情報を設定する

をする必要があります

a. WkWebView の初期化時に document.cookie_session_id を設定する

WKUserScript 経由で document.cookie_session_id を設定することで、初回リクエスト時以降もSession情報を保つことができます

let userContentController = WKUserContentController()
let script = "document.cookie='_session_id=セッションID; domain=サーバードメイン; path=Cookieパス;"
let cookieScript = WKUserScript(source: script, injectionTime: WKUserScriptInjectionTime.atDocumentStart, forMainFrameOnly: false)
userContentController.addUserScript(cookieScript)

let configuration = WKWebViewConfiguration()
configuration.userContentController = userContentController

セッションID、サーバードメイン、Cookieパスについては、[webView(_:decidePolicyFor:decisionHandler:)]の navigationResponse で渡される HTTPCookie の値を確認してみてください

b. WkWebVie の初回リクエスト時にCookie情報を設定する

初回リクエスト時にSession情報を設定してリクエストするためには、load メソッドに渡す URLRequest のインスタンスにCookie情報を設定する必要があります
注意点として、 httpShouldHandleCookies を falseに設定してリクエストする必要があります
trueにした場合、 HTTPCookieStrage の値を共有してしまい、正しくSession情報が渡せない可能性があります

var request = URLRequest(url: url)
request.httpShouldHandleCookies = false
request.setValue("_session_id=セッションID", forHTTPHeaderField: "Cookie")
webview.load(request)

参考

77
59
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
77
59

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?