ホームページ  >  記事  >  ウェブフロントエンド  >  クロスドメイン Ajax に対する最も包括的なソリューション

クロスドメイン Ajax に対する最も包括的なソリューション

韦小宝
韦小宝オリジナル
2018-03-08 16:00:341862ブラウズ

初めて JavaScript を学び始めたとき、私は ajax クロスドメインが何なのか知りませんでしたが、偉い人たちがドメイン間の ajax クロスドメインの問題について話しているのをよく聞きました。私のようなクラスメートもいると思うので、話しましょう。今日はそれについて Ajax クロスドメインとは何なのか、そして Ajax クロスドメインを解決する方法は何なのかを見てみましょう。

前書き

クロスドメインに関しては、この記事では N 種類の Ajax リクエスト クロスドメインのみに焦点を当てています (Ajax クロスドメインはブラウザーの「同一オリジン ポリシー」の一部にすぎません。その他には Cookie も含まれます)。クロスドメインドメイン iframe クロスドメイン、LocalStorage クロスドメインなどはここでは紹介しません)、内容は大まかに以下の通りです:

1. ajax クロスドメインとは

原則

パフォーマンス(遭遇するいくつかの問題と解決策を整理しました)

2. Ajaxクロスドメインを解決する方法

JSONPメソッド

CORSメソッド

プロキシリクエスト方法

3. Ajaxクロスドメインの解析方法

httpパケットキャプチャ解析

いくつかの例

アヤックスクロスとは-domain

Ajax クロスドメインの原則

Ajax には、ブラウザの「同一オリジン ポリシー」が原因でクロスドメイン リクエスト エラーの問題が発生する可能性があります。ブラウザの同一オリジンポリシーとその回避方法を参照してください

CORSリクエスト原則

CORSはW3C標準であり、正式名称は「クロスオリジンリソース共有」です。これにより、ブラウザーがクロスオリジン サーバーに XMLHttpRequest リクエストを発行できるようになり、AJAX が同じオリジンからのみ使用できるという制限が克服されます。

基本的に、現在のすべてのブラウザーは CORS 標準を実装しています。実際、ほとんどすべてのブラウザーの Ajax リクエストは CORS メカニズムに基づいていますが、フロントエンド開発者はそれを気にしない可能性があります (つまり、現在の CORS ソリューションは主に次の方法を検討しています)。バックグラウンドを実装します)。

CORS については、読むことを強くお勧めします


クロスドメインリソース共有のための CORS の詳細な説明

さらに、実装概略図 (簡易版) もここにまとめられています:

クロスドメイン Ajax に対する最も包括的なソリューション

ブラウザは、CORS リクエストを単純なリクエスト (単純なリクエスト) とそれほど単純ではないリクエスト (そうでないリクエスト) の 2 つのカテゴリに分類します。簡単なリクエスト)。以下の2つの条件を同時に満たしていれば簡単なリクエストです。

1. リクエストメソッドは、HEAD、GET、POSTのいずれかです

2. HTTPヘッダー情報は次のフィールドを超えません:

1. 2を受け入れる。 Accept-Language

3.コンテンツ言語 4.最終イベント ID

5. Content-Type (application/x-www-form-urlencoded、multipart/form-data、text/plain の 3 つの値に制限)

上記 2 つの条件を同時に満たさないリクエストは単純ではないリクエストです。

ajaxクロスドメインパフォーマンス

正直、最初は記事にまとめて解決策として使っていたのですが、後になってみたらまだやり方が分からない人が多いことが分かりました。デバッグするしかありませんが、時間と労力がかかります。ただし、分析してもクロスドメインかどうかは対応するパフォーマンスで判断するだけなので、これは非常に重要です。

ajax リクエストを行う際に、クロスドメイン現象が発生し、それが解決されていない場合、次の動作が発生します: (これは ajax リクエストであることに注意してください。なぜ http リクエストは OK ですが、ajax がダメなのかは述べないでください) 、ajax にはクロスドメインが伴うため、http リクエスト OK だけでは十分ではありません) 注: 特定のバックエンドのクロスドメイン構成については、質問の概要を参照してください。

最初の現象: 要求されたリソースに「Access-Control-Allow-Origin」ヘッダーが存在せず応答には HTTP ステータス コード 404 が含まれていました

クロスドメイン Ajax に対する最も包括的なソリューション

これが発生する理由状況は次のとおりです。

1. この Ajax リクエストは「非単純リクエスト」であるため、リクエストの前にプリフライト リクエスト (OPTIONS) が送信されます。 2. サーバー側のバックグラウンド インターフェイスでは OPTIONS リクエストが許可されません。アドレス

解決策: バックエンドはオプション要求を許可します

2 番目の現象:

要求されたリソースに 'Access-Control-Allow-Origin' ヘッダーが存在しません

、そして 応答HTTP ステータス コード 405 がありました


クロスドメイン Ajax に対する最も包括的なソリューション

この現象は最初の現象とは異なりますが、バックグラウンド メソッドでは OPTIONS リクエストが許可されていますが、一部の

設定ファイル

(セキュリティ構成として) ブロックしてください OPTIONS リクエストによりこの現象が発生します解決策: バックエンドで対応するセキュリティ構成をオフにしてください

3 番目の現象:

要求されたリソースに「Access-Control-Allow-Origin」ヘッダーが存在しません

, andstatus 200

クロスドメイン Ajax に対する最も包括的なソリューション

この現象は、1つ目と2つ目とは異なります。この場合、サーバー側のバックグラウンドでOPTIONSリクエストが許可され、インターフェイスでもOPTIONSリクエストが許可されますが、次の場合に発生します。ヘッダーが一致する不一致現象

たとえば、一部のヘッダー サポート (共通の X-Requested-With ヘッダーなど) が欠落しているなど、オリジン ヘッダー チェックが一致しない場合、サーバーは応答をフロントエンドがこの XHR.onerror を検出すると、フロントエンド コンソールにエラーが報告されます

解決策: 対応するヘッダー サポートをバックエンドに追加します

4 番目の現象:

heade に複数の値が含まれています '* ,*'

クロスドメイン Ajax に対する最も包括的なソリューション

症状は、バックグラウンド応答の http ヘッダー情報に 2 つの Access-Control-Allow-Origin:*

正直に言うと、この問題の主な原因は次のとおりです。クロスドメイン構成を実行する人は原理を理解していないため、次のような構成が繰り返されます。

1. .net バックエンドで一般的 (通常、オリジンは web.config で一度構成され、その後オリジンは手動で構成されます)コードに追加 (たとえば、コードは return * を手動で設定します))

2. .net バックグラウンドでの共通 (IIS とプロジェクトの webconfig の両方で Origin:* を設定します)

ソリューション (one-to -1 つの対応):

1. コードに手動で追加された * を削除し、プロジェクト構成でのみ使用することをお勧めします 2. IIS* の下の構成を削除し、プロジェクト内の構成のみを使用することをお勧めします

Ajax クロスドメインの解決方法

一般に、Ajax クロスドメイン ソリューションは、次のように JSONP または CORS を通じて解決されます: (JSONP はほとんど使用されなくなったため、JSONP だけを理解してください)

クロスドメインの問題を解決するための JSONP メソッド

jsonp は、クロスドメインの問題を解決するための比較的古いソリューションです (実際には推奨されません)。ここで簡単に紹介します (実際のプロジェクトで JSONP を使用したい場合は、通常、 JSONP をカプセル化する JQ およびその他のクラス ライブラリを使用して、Ajax リクエストを作成します)

実装原則

JSONP がクロスドメイン ソリューションの解決に使用できる理由は、主に <script> スクリプトにクロスドメインがあるためです。機能があり、JSONP はこれを利用してそれを実現します。具体的な原理は図の通りです</script>

実装プロセス

JSONP の実装手順は大まかに次のとおりです (ソースの記事を参照)

1. クライアント Web ページは、<script> 要素を追加してサーバーに JSON データを要求します。同一生成元ポリシーに従う 制限事項</script>

function addScriptTag(src) {
  var script = document.createElement(&#39;script&#39;);
  script.setAttribute("type","text/javascript");
  script.src = src;
  document.body.appendChild(script);
}

window.onload = function () {
  addScriptTag(&#39;http://example.com/ip?callback=foo&#39;);
}

function foo(data) {
  console.log(&#39;response data: &#39; + JSON.stringify(data));
};

リクエスト時、インターフェースアドレスは構築されたスクリプトタグの src として使用されます。 このように、スクリプトタグが構築されると、最終的な src はインターフェースによって返されるコンテンツになります

。 2. サーバーの対応するインターフェイスは戻りパラメータの外にあります。 関数ラッピング層を追加します

foo({
  "test": "testData"
});

3. <script> 要素によって要求されたスクリプトはコードとして直接実行されます。このとき、ブラウザが foo 関数を定義していれば、すぐに関数が呼び出されます。パラメーターとしての JSON データは文字列ではなく <a href="http://www.php.cn/js/js-jsref-tutorial.html" target="_blank">JavaScript オブジェクト として扱われるため、JSON.parse を使用する手順が不要になります。 </script>

一般的なJSONPインターフェースと通常のインターフェースでは返されるデータが異なるため、インターフェースをJSONO互換にする場合は、対応するコールバックキーワードパラメータがあるかどうかを判断する必要があります。それ以外の場合は、通常のデータが返されます

使用上の注意

JSONP の実装原則に基づいているため、JSONP は「GET」リクエストのみにすることができます。より複雑な POST やその他のリクエストを行うため、そのような状況に遭遇した場合は、以下の CORS ソリューションを参照する必要があります。 クロスドメイン (したがって、現在は基本的に排除されています)

CORS はクロスドメインの問題を解決します

CORS の原理は上で紹介しました。ここで主に紹介するのは、実際のプロジェクトでバックエンドをどのように構成する必要があるかです。問題を解決するために (プロジェクトの実践の多くはバックエンドによって解決されるため)、以下に一般的なバックエンドをいくつか示します。解決策:

PHP バックエンド構成

PHP バックグラウンド構成は、すべてのバックグラウンドの中でほぼ最も一般的です。以下の手順に従ってください:

ステップ 1: クロスドメインを許可するように PHP バックエンドを構成する

<?php
header(&#39;Access-Control-Allow-Origin: *&#39;);
header(&#39;Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept&#39;);
//主要为跨域CORS配置的两大基本信息,Origin和headers

ステップ 2: 構成するApache Webサーバーのクロスドメイン(httpd.conf内)

元のコード

<Directory />
    AllowOverride none
    Require all denied
</Directory>

以下のコードに変更

<Directory />
    Options FollowSymLinks
    AllowOverride none
    Order deny,allow
    Allow from all
</Directory>

Node.jsのバックグラウンド設定(Express Framework)

Node.jsのバックグラウンドは比較的シンプルで設定可能です。 Express を使用して次のように設定するだけです:

app.all(&#39;*&#39;, function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "X-Requested-With");
    res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
    res.header("X-Powered-By", &#39; 3.2.1&#39;)
        //这段仅仅为了方便返回json而已
    res.header("Content-Type", "application/json;charset=utf-8");
    if(req.method == &#39;OPTIONS&#39;) {
        //让options请求快速返回
        res.sendStatus(200); 
    } else { 
        next(); 
    }
});

JAVA バックグラウンド設定

JAVA バックグラウンド設定は次の手順に従うだけです:

ステップ 1: 依存する jar パッケージを取得する

ダウンロード cors-filter-1.7 .jarjava-property-utils-1.9.jar これら 2 つのライブラリ ファイルは lib ディレクトリに配置されます。 (対応するプロジェクトの webcontent/WEB-INF/lib/ の下に配置します)

ステップ 2: プロジェクトが Maven でビルドされている場合は、次の依存関係を pom.xml に追加してください: (Maven でない場合は無視してください) )

<dependency>
    <groupId>com.thetransactioncompany</groupId>
    <artifactId>cors-filter</artifactId>
    <version>[ version ]</version>
</dependency>

その中で、バージョンは最新の安定バージョンである必要があります、CORSFilter

ステップ 3: CORS 構成をプロジェクトの Web.xml (App/WEB-INF/web.xml) に追加します

<!-- 跨域配置-->    
<filter>
        <!-- The CORS filter with parameters -->
        <filter-name>CORS</filter-name>
        <filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
        
        <!-- Note: All parameters are options, if omitted the CORS 
             Filter will fall back to the respective default values.
          -->
        <init-param>
            <param-name>cors.allowGenericHttpRequests</param-name>
            <param-value>true</param-value>
        </init-param>
        
        <init-param>
            <param-name>cors.allowOrigin</param-name>
            <param-value>*</param-value>
        </init-param>
        
        <init-param>
            <param-name>cors.allowSubdomains</param-name>
            <param-value>false</param-value>
        </init-param>
        
        <init-param>
            <param-name>cors.supportedMethods</param-name>
            <param-value>GET, HEAD, POST, OPTIONS</param-value>
        </init-param>
        
        <init-param>
            <param-name>cors.supportedHeaders</param-name>
            <param-value>Accept, Origin, X-Requested-With, Content-Type, Last-Modified</param-value>
        </init-param>
        
        <init-param>
            <param-name>cors.exposedHeaders</param-name>
            <!--这里可以添加一些自己的暴露Headers   -->
            <param-value>X-Test-1, X-Test-2</param-value>
        </init-param>
        
        <init-param>
            <param-name>cors.supportsCredentials</param-name>
            <param-value>true</param-value>
        </init-param>
        
        <init-param>
            <param-name>cors.maxAge</param-name>
            <param-value>3600</param-value>
        </init-param>

    </filter>

    <filter-mapping>
        <!-- CORS Filter mapping -->
        <filter-name>CORS</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

次のことに注意してください上記の設定ファイルを web.xml の前に置き、最初のフィルターとして存在させてください (複数のフィルターが存在する可能性があります)

ステップ 4: セキュリティ モジュール設定エラーの可能性があります (会社のプライベート フレームワークなど、一部のフレームワークにはセキュリティがあることに注意してください)はい、これらのセキュリティ モジュール設定がクロスドメイン設定に影響を与える場合があります。この場合、最初にそれらをオフにしてみてください)

JAVA Spring Boot 設定

20171230 補足

単純なグローバル設定のみをリストします

@Configuration
public class CorsConfig {

    private CorsConfiguration buildConfig() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();        
        // 可以自行筛选
        corsConfiguration.addAllowedOrigin("*");
        corsConfiguration.addAllowedHeader("*");
        corsConfiguration.addAllowedMethod("*");        
        return corsConfiguration;
    }

    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        
        source.registerCorsConfiguration("/**", buildConfig());        
        return new CorsFilter(source);  
    }
}

新しい構成。次に、構成アノテーションを追加すると、構成が成功します

PS: メソッドのこの部分は含まれており、個人的には実践されていませんが、フィードバックによると、理論的には実行可能です

NETバックグラウンド設定

.NET のバックグラウンド設定については、次の手順を参照してください:

ステップ 1: Web サイトの設定

コントロール パネルを開き、[管理ツール] を選択し、[iis] を選択して [参照] を選択します。 Web サイトが配置されているディレクトリに移動し、メモ帳を使用して web.config ファイルを開き、次の構成情報を追加して、Web サイトを再起動します

クロスドメイン Ajax に対する最も包括的なソリューション

请注意,以上截图较老,如果配置仍然出问题,可以考虑增加更多的headers允许,比如:

"Access-Control-Allow-Headers":"X-Requested-With,Content-Type,Accept,Origin"

第二步:其它更多配置,如果第一步进行了后,仍然有跨域问题,可能是:

1、接口中有限制死一些请求类型(比如写死了POST等),这时候请去除限 制

2、接口中,重复配置了Origin:*,请去除即可

3、IIS服务器中,重复配置了Origin:*,请去除即可

代理请求方式解决接口跨域问题

注意,由于接口代理是有代价的,所以这个仅是开发过程中进行的。

与前面的方法不同,前面CORS是后端解决,而这个主要是前端对接口进行代理,也就是:

1、前端ajax请求的是本地接口

2、本地接口接收到请求后向实际的接口请求数据,然后再将信息返回给前端

3、一般用node.js即可代理

关于如何实现代理,这里就不重点描述了,方法和多,也不难,基本都是基于node.js的。

搜索关键字node.js,代理请求即可找到一大票的方案。

OPTIONS预检的优化

Access-Control-Max-Age:

这个头部加上后,可以缓存此次请求的秒数。

在这个时间范围内,所有同类型的请求都将不再发送预检请求而是直接使用此次返回的头作为判断依据。

非常有用,可以大幅优化请求次数

如何分析ajax跨域

上述已经介绍了跨域的原理以及如何解决,但实际过程中,发现仍然有很多人对照着类似的文档无法解决跨域问题,主要体现在,前端人员不知道什么时候是跨域问题造成的,什么时候不是,因此这里稍微介绍下如何分析一个请求是否跨域:

抓包请求数据

第一步当然是得知道我们的ajax请求发送了什么数据,接收了什么,做到这一步并不难,也不需要fiddler等工具,仅基于Chrome即可

1、Chrome浏览器打开对应发生ajax的页面,F12打开Dev Tools

2、发送ajax请求

3、右侧面板->NetWork->XHR,然后找到刚才的ajax请求,点进去

示例一(正常的ajax请求)

クロスドメイン Ajax に対する最も包括的なソリューション

上述请求是一个正确的请求,为了方便,我把每一个头域的意思都表明了,我们可以清晰的看到,接口返回的响应头域中,包括了

Access-Control-Allow-Headers: X-Requested-With,Content-Type,Accept
Access-Control-Allow-Methods: Get,Post,Put,OPTIONS
Access-Control-Allow-Origin: *

所以浏览器接收到响应时,判断的是正确的请求,自然不会报错,成功的拿到了响应数据。

示例二(跨域错误的ajax请求)

为了方便,我们仍然拿上面的错误表现示例举例。

クロスドメイン Ajax に対する最も包括的なソリューション

这个请求中,接口Allow里面没有包括OPTIONS,所以请求出现了跨域、

クロスドメイン Ajax に対する最も包括的なソリューション

这个请求中,Access-Control-Allow-Origin: *出现了两次,导致了跨域配置没有正确配置,出现了错误。

更多跨域错误基本都是类似的,就是以上三样没有满足(Headers,Allow,Origin),这里不再一一赘述。

示例三(与跨域无关的ajax请求)

当然,也并不是所有的ajax请求错误都与跨域有关,所以请不要混淆,比如以下:

クロスドメイン Ajax に対する最も包括的なソリューション

更多

基本上都是这样去分析一个ajax请求,通过Chrome就可以知道了发送了什么数据,收到了什么数据,然后再一一比对就知道问题何在了。

总结

跨域是一个老生常谈的话题,网上也有大量跨域的资料,并且有不少精品(比如阮一峰前辈的),但是身为一个前端人员不应该浅尝而止,故而才有了本文。


以上がクロスドメイン Ajax に対する最も包括的なソリューションの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。