Edited at

【Swift】ユーザー認証APIを通した後、同一セッションとしてUIWebViewを表示する

More than 3 years have passed since last update.

WebViewベースのアプリを作るときにログインフォームをネイティブで作ってID・Passwordを入力し、その値をAPIに投げてユーザー認証を行う。その後に、認証を通したユーザーとしてログインした状態でWebViewを表示したいという場合があるかと思います。

Webブラウザでログインして次の画面に遷移したときに同一ユーザーとして認識されている状態を作る感じです。Googleにログインしたり、Pixivにログインしたり、ああいうやつです。

僕は最近こんな場面がありました。

ので、どんな流れかを備忘録も兼ねて書いていきます。


Cookieの取得

同一セッションであることを証明する方法としてCookieを使う方法があります。

APIを投げた後、返ってきたResponse部にCookieが付加されているはずなのでそれをNSHTTPCookieに保持させます。

responseをprintlnで出力すると"Set-cookie" = "hogehoge"とか書いてあると思います。

今回は例としてAlamofireで取得した結果から取得します。

Alamofire.request(.POST, "http://hogehogeURL", parameters: loginInfo).

responseJSON(options: .AllowFragments, completionHandler: { (request, response, json, error) -> Void in

let cookies = NSHTTPCookie.cookiesWithResponseHeaderFields(response!.allHeaderFields, forURL: response!.URL!)

for var i = 0; i < cookies.count; i++ {
let cookie = cookies[i] as! NSHTTPCookie
// ここで取得したCookieを保持
NSHTTPCookieStorage.sharedHTTPCookieStorage().setCookie(cookie)
}
}


WebViewに取得したCookieを渡す

NSMutableURLRequestを使用して接続先のURL情報に加えて、先ほど取得したCookieも付加してWebViewをロードします。

これを実行する前にwebViewのオブジェクトは生成しておいてあります。

func loadWebView() {

// 接続先のURL
let url = NSURL(string: "http://fugafugaURL")

// さっきPOSTを投げた認証するためのURL
let authUrl = NSURL(string: "http://hogehogeURL")

let request = NSMutableURLRequest(URL: url!)

let cookies = NSHTTPCookieStorage.sharedHTTPCookieStorage().cookiesForURL(authUrl!)
let header = NSHTTPCookie.requestHeaderFieldsWithCookies(cookies!)
request.allHTTPHeaderFields = header

// webViewのロードを開始
webView.loadRequest(request)
}


まとめ

もしかするとこういうやり方をするのはそもそも設計段階で間違っているとか、もっと良いやり方があるのかもしれないです。何かツッコミ等あればどしどしください。

通信周りよくわかってなかったですが、実装にあたって調べる機会を持てたので良かったです。


追記:2016/02/16 Alamofire(3.x系) + Swift 2.0対応

Alamofireが3.x系になってからクロージャの中のパラメータが結構変わったのが気になったので追記です。

あと気持ち程度のguard記述。

(若干強制的にキャストしてたり、強制アンラップしてたりする、、、よ、、、)

Alamofire.request(.POST, "http://hogehogeURL", parameters: ["loginInfo":"loginInfo"]).responseJSON { response in

guard let r = response.response else { return }

let cookies = NSHTTPCookie.cookiesWithResponseHeaderFields(r.allHeaderFields as! [String: String], forURL: r.URL!)

for var i = 0; i < cookies.count; i++ {
let cookie = cookies[i]
// ここで取得したCookieを保持
NSHTTPCookieStorage.sharedHTTPCookieStorage().setCookie(cookie)
}
}