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

【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)
    }
}
ktanaka117
百合好きのダンボールの人です。 SwiftでiOSアプリを開発していて、最近のホットトピックはテスト、設計、リファクタリング。 Twitter: @ktanaka117
http://tanakalivesinsendai.hatenablog.com/
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
ユーザーは見つかりませんでした