Help us understand the problem. What is going on with this article?

WKWebViewでのSessionの共有

More than 1 year has passed since last update.

概要

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)

参考

nikadon
PaletteCloudという不動産テックの会社でエンジニアをやってます
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした