web-dev-qa-db-ja.com

Cordovaは一部のAndroidデバイスでリクエストに応じてOriginを送信しません

これは一部のAndroidデバイスで発生する問題です。

私はSamsung Galaxy A5 (2017)とGoogle Chrome version 76.0.3809.89およびAndroidバージョン8.0.0。

Cordovaアプリケーションをこのデバイスに初めてデプロイしてPOSTリクエストを行うと、CORSに関するエラーが表示されます。

Access to XMLHttpRequest at 'http://foo.com/bar' from Origin 'file://' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Chromeの開発ツールのネットワークタブから、このPOSTリクエスト、Originパラメータがないことがわかります。

タスクマネージャーからアプリケーションを閉じて再起動すると、この要求を正常に実行でき、chromeは要求に応じて 'Origin'パラメーターを送信します。

デバイスの設定からアプリケーションのデータを削除すると、問題を再現できます。

これはContent-Security-Policyまたはcordova-whitelist-plugin構成の問題ではないと確信しています。他の一部のAndroidデバイスでは、アプリケーションが正常に動作するためです。

私が言及する必要がある他の何かは、横断歩道プラグインで私はこの問題を持っていなかったことです。

10
yannisalexiou

同じ問題が発生しています。最初に、アプリがChrome=バージョンを検出する回避策を実装しました。最初にバージョン76が表示されると、アプリが自動的に再起動されます。ほとんどのユーザーは、再起動に気付くことすらありません。回避策はいくつかのレポートに基づいて、問題はChroe 76がインストールされた後のアプリの最初の実行中にのみ発生し、再起動後に完全に消えるであろうと判明しました。しかし、問題はしばしばランダムに見えるようになりました。十分ではなかった。

幸いにもサーバー側を制御しているので、そこで回避策を実装しました。基本的には、file:// Originを受け入れるだけです。この回避策のセキュリティへの影響は、確かに個々のアプリケーションに依存するため、同様のものの実装を検討する場合に備えて、慎重に検討してください。

今回のケースでは、追加の課題に直面していたASP.NETを使用しています。残念ながら、file://をオリジンとして指定すると、EnableCorsAttributeは失敗します。これは、各オリジンにホスト名が存在する必要があるCORS仕様に準拠しています(*を指定する場合を除く)。したがって、最終的に次のソリューションを思いついた(もちろんASP.NETに固有)。

Origin file://の場合は検証ロジックをオーバーライドし、他のすべての場合はネストされたプロバイダー(元のプロバイダー)に委任するICorsPolicyProviderを作成します。

    /// <summary>
    /// Object that allows clients with `file://` Origin. This is used as a workaround
    /// for issues on Android devices running Chrome 76. See
    /// https://bugs.chromium.org/p/chromium/issues/detail?id=991107#c14
    /// 
    /// Simply adding `file://` to the allowed origins list doesn't work, because by
    /// specification a hostname is required.
    /// 
    /// This workaround should be removed as soon as Chrome 76 distribution has dropped
    /// sufficiently.
    /// </summary>
    // TODO: Remove this workaround once Chrome 76 is not around anymore.
    public class CorsPolicyProviderAcceptingFileOrigin : ICorsPolicyProvider
    {
        public readonly ICorsPolicyProvider inner;

        public CorsPolicyProviderAcceptingFileOrigin(ICorsPolicyProvider inner)
        {
            this.inner = inner;
        }

        public async Task<CorsPolicy> GetCorsPolicyAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            if (
                request.Headers.TryGetValues("Origin", out IEnumerable<string> origins)
                && origins.SequenceEqual(new[] { "file://" })
                )
            {
                var policy = new CorsPolicy()
                {
                    AllowAnyHeader = true,
                    AllowAnyMethod = true,
                    AllowAnyOrigin = false,
                };
                policy.Origins.Add("file://");

                return policy;
            }

            return await this.inner.GetCorsPolicyAsync(request, cancellationToken);
        }
    }

そして、それをWebApiConfig.csで次のように使用します。

// get the original EnableCorsAttribute
ICorsPolicyProvider cors = ...;

// this is a workaround for Android devices running Chrome 76 and should be removed in future versions.
// See https://bugs.chromium.org/p/chromium/issues/detail?id=991107
cors = new CorsPolicyProviderAcceptingFileOrigin(cors);

config.EnableCors(cors);
2
MarkusM

これは、76バージョンに興味深いChromium webviewの未解決のバグです。この特定のバージョンでは、OOR-CORSは最初の実行では有効のままです。

https://bugs.chromium.org/p/chromium/issues/detail?id=991107#c14

変更リストは76ブランチに直接マージされます。

7
systempuntoout

同じ問題が発生しています... AJAXコールは、Cordovaプロジェクトの最初のコールドスタート後に機能しません。アプリを再起動すると(アプリをバックグラウンドから削除)、機能します。 。ChromiumWebViewバージョンに問題があるようです...非常に醜い回避策を見つけました。

https://github.com/dpa99c/cordova-diagnostic-plugin#restart

プラグインし、最初のコールドスタート後にアプリを再起動します。コールドスタートフラグのlocalStorageを確認します。見つからない場合は、アプリを再起動してください。

0
Nagy Istvan