36

ダウンロードしたいファイル(CSV)があります。Web サイトのログイン画面の背後にあります。WKWebViewユーザーがログインできるようにし、ログイン後にアプリにファイルをダウンロードさせるように表示したかったのです。

ユーザーがWebサイトにログインした後、外部でファイルをダウンロードしようとしましたWKWebViewが、目的のファイルではなく、ログインフォームを含むhtmlドキュメントをダウンロードするため、セッションデータがサンドボックス化されているようです.

WKUserScriptまた、オブジェクトに a を追加しようとしましたWKUserContentControllerが、HTML 以外のファイルが読み込まれるとスクリプトが実行されません。

ユーザーが 経由でログインできるようにしながら、このファイルにアクセスする方法はありますWKWebViewか?

4

5 に答える 5

96

現在、WKWebView インスタンスは、デフォルトのネットワーク ストレージ (NSURLCache、NSHTTPCookieStorage、NSCredentialStorage) と、ネットワーク リクエストのカスタマイズに使用できる標準のネットワーク クラス (NSURLProtocol など) を無視します。

したがって、WKWebView インスタンスの Cookie はアプリの標準の Cookie ストレージに保存されないため、標準の Cookie ストレージのみを使用する NSURLSession/NSURLConnection は WKWebView の Cookie にアクセスできません (これがおそらく問題です: 「ログインステータス」はおそらく Cookie に保存されますが、NSURLSession/NSURLConnection は Cookie を認識しません)。

キャッシュ、資格情報などについても同様です。WKWebView には独自のプライベート ストレージがあるため、標準の Cocoa ネットワーク クラスとはうまく連携しません。

NSURLProtocol も WKWebView でサポートされていないため、リクエストをカスタマイズ (独自のカスタム HTTP ヘッダーを追加する、既存のヘッダーを変更するなど) したり、独自のカスタム URL スキームを使用したりすることはできません。

そのため、現在 WKWebView は、Cocoa の標準ネットワーク API に参加していないため、多くのアプリではほとんど役に立ちません。

iOS 8 がリリースされるまで Apple がこれを変更してくれることを願っています。

バグ レポートを Apple に送信して、Apple がこれらの問題が深刻であり、修正する必要があることを認識できるようにします。

于 2014-07-27T15:00:30.350 に答える
15

リクエストから返されるレスポンス Cookie を確認しましたか。このようなデリゲート メソッドを使用できます。

- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{
    NSHTTPURLResponse *response = (NSHTTPURLResponse *)navigationResponse.response;
    NSArray *cookies =[NSHTTPCookie cookiesWithResponseHeaderFields:[response allHeaderFields] forURL:response.URL];

    for (NSHTTPCookie *cookie in cookies) {
        [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
    }

    decisionHandler(WKNavigationResponsePolicyAllow);
}
于 2014-12-12T19:36:05.833 に答える
1

私はあなたがやろうとしていることと同様のことを達成しました:

  • すでに行っているように、Web ビューを使用してログインします
  • navigationDelegateあなたのウェブビューに
  • -webView:decidePolicyForNavigationResponse:decisionHandlerデリゲートに実装する
  • そのデリゲート メソッドが呼び出されると (ユーザーがログインした後)、検査navigationResponse.response(にキャスト) して、認証されたセッションに必要なセッション情報を含むヘッダーをNSHTTPURLResponse*探すことができます。Set-Cookie
  • Cookie次に、応答で指定された Cookie を使用して要求でヘッダーを手動で指定することにより、CSV をダウンロードできます。

デリゲート メソッドは、「メイン フレーム」リクエストに対してのみ呼び出されることに注意してください。つまり、AJAX リクエストまたは内部フレームはそれをトリガーしません。これが機能するには、ページ全体を更新する必要があります。

AJAX リクエストや iframe などの動作をトリガーする必要がある場合は、JavaScript を挿入する必要があります。

于 2015-02-25T12:40:27.337 に答える
1

Javascript 経由で Cookie を取得できます。

取得した Cookie を使用して、ファイルを手動でダウンロードできます。

webView.evaluateJavaScript("(function() { return document.cookie })()", completionHandler: { (response, error) -> Void in
  let cookie = response as! String
  let request = NSMutableURLRequest(URL: docURL)
  request.setValue(cookie, forHTTPHeaderField:  "Cookie")

  NSURLSession.sharedSession().dataTaskWithRequest(request, completionHandler: { (data, response, error) in
    // Your CSV file will be in the response object
  }).resume()
})
于 2016-03-14T07:37:34.133 に答える
0

userContentController didReceiveScriptMessage からのリクエストを試みると、セッション Cookie がないようです。

ただし、decisionPolicyForNavigationAction から呼び出されると、次のコードはログインしていることを検出します。

     let urlPath: String = "<api endpoint at url at which you are logged in>"

    let url = NSURL(string: urlPath)
    let session = NSURLSession.sharedSession()
    let task = session.dataTaskWithURL(url!, completionHandler: {data, response, error -> Void in

        let string1 = NSString(data: data, encoding: NSUTF8StringEncoding)
        println(string1)
        println(data)
        if(error != nil) {
            println("Error sending token to server")
            // Print any error to the console
            println(error.localizedDescription)
        }
        var err: NSError?

    })

    task.resume()
于 2015-07-10T02:30:42.897 に答える