ホームページ  >  記事  >  ウェブフロントエンド  >  フロントエンドのクロスドメイン組織_html/css_WEB-ITnose

フロントエンドのクロスドメイン組織_html/css_WEB-ITnose

WBOY
WBOYオリジナル
2016-06-21 08:48:251254ブラウズ

クロスドメインの並べ替え

1. クロスドメインのリソース共有 CORS

Web 開発の場合、ブラウザーの同一オリジン ポリシーにより、一部のハッキング手法はドメインを越えてリソースを取得するためによく使用されますが、ハッキング手法は常にハッキングです。 W3C が CORS 「クロスオリジン リソース共有」という標準を発表するまでは。

これにより、ブラウザーがクロスオリジン サーバーに XMLHttpRequest リクエストを発行できるようになり、AJAX が同じオリジンからのみ使用できるという制限が克服されます。

まず、互換性のために、CORS はブラウザーとサーバーの両方でサポートされている必要があります。主に ie10 以降であり、その他の最新のブラウザーもサポートされています。

http://caniuse.com/#feat=cors

CORS クロスドメインを使用する場合、プロセスは実際には通常の Ajax と同じですが、ブラウザーはこれがクロスであることを検出します。 -domain リクエストを行うと、検証などのいくつかの処理が自動的に行われるため、サーバーがサポートを提供している限り、フロントエンドは追加の処理を行う必要はありません。

2 種類のリクエスト

CORS リクエストは、セキュリティのためにブラウザによって実行される処理の一部であり、ブラウザによって実行される動作も異なります。もちろん、追加の処理を行う必要はなく、ブラウザが自動的に処理します。

1. 簡単なリクエスト

以下の 2 つの条件を同時に満たす限り、簡単なリクエストです。

条件

1) 请求方法是以下三种方法中的一个:HEADGETPOST2)HTTP的头信息不超出以下几种字段:AcceptAccept-LanguageContent-LanguageLast-Event-IDContent-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

プロセス

単純なクロスドメインリクエストの場合、ブラウザは自動的に情報を追加します。 Origin フィールドは、このリクエストの送信元 (プロトコル + ドメイン名 + ポート) を示します。サーバーはこの値を取得し、このリクエストに同意して返すかどうかを決定します。

// 请求GET /cors HTTP/1.1Origin: http://api.qiutc.meHost: api.alice.comAccept-Language: en-USConnection: keep-aliveUser-Agent: Mozilla/5.0...

1. サーバーは

サーバーがこのリクエストを許可すると、さらにいくつかのヘッダー フィールドを返します。

// 返回Access-Control-Allow-Origin: http://api.qiutc.meAccess-Control-Allow-Credentials: trueAccess-Control-Expose-Headers: InfoContent-Type: text/html; charset=utf-8

Access-Control で始まるこれら 3 つのフィールドは、それぞれ次のことを表します。

    Access-Control -Allow-Origin が必要です。その値は、リクエスト中の Origin フィールドの値、または任意のドメイン名からのリクエストが受け入れられることを示す * です。
  • Access-Control-Allow-Credentials オプション。その値は、Cookie の送信を許可するかどうかを示すブール値です。デフォルトでは、Cookie は CORS リクエストに含まれません。 true に設定すると、サーバーがリクエストに Cookie を含めてサーバーに送信することを明示的に許可します。 Cookie を送信する必要がある場合は、AJAX リクエストの withCredentials 属性をオンにすることにも注意する必要があります。 var xhr = new XMLHttpRequest(); Control-Allow-Origin を * に設定することはできず、明確なドメイン名を設定する必要があります。要求された Web ページと一致するように指定されています。同時に、Cookie は同一オリジン ポリシーに従います。サーバー ドメイン名で設定された Cookie のみがアップロードされ、元の Web ページ コードの document.cookie は Cookie を読み取ることができません。サーバーのドメイン名。
  • Access-Control-Expose-Headers オプション。 CORS リクエストを作成する場合、XMLHttpRequest オブジェクトの getResponseHeader() メソッドは、Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、および Pragma の 6 つの基本フィールドのみを取得できます。他のフィールドを取得したい場合は、Access-Control-Expose-Headers で指定する必要があります。上記の例では、getResponseHeader('Info') が Info フィールドの値を返すことができることを指定しています。
  • 2. サーバーは

を拒否します。 もちろん、インターフェイスがランダムに呼び出されるのを防ぐために、許可されていないソースを制限する必要があります。場合でも、サーバーは通常の「HTTP 応答には Access-Control-Allow-Origin フィールドがありません」を返します。このクロスドメイン要求の戻りヘッダー情報にこのフィールドがないことがブラウザで検出された場合、エラーがスローされます。これは、XMLHttpRequest の onerror コールバックによってキャプチャされます。

応答ステータス コードは 200 である可能性があるため、このエラーは HTTP ステータス コードでは判断できません。

2. 非単純リクエスト

条件

単純なリクエスト以外の CORS リクエストが行われました。非単純リクエストとは、リクエストメソッドが PUT または DELETE であるか、Content-Type フィールドのタイプが application/json であるなど、サーバーに対して特別な要件を持つリクエストです。

プロセス

1) プリフライトリクエスト

単純なリクエストではない CORS リクエストは、正式な通信の前に「プリフライトリクエスト」「チェック」と呼ばれる HTTP クエリリクエストを追加します。 " リクエスト (プリフライト)。

ブラウザはまずサーバーに、現在の Web ページのドメイン名がサーバーの許可リストに含まれているかどうか、またどの HTTP 動詞とヘッダー情報フィールドを使用できるかを尋ねます。肯定的な応答を受信した場合にのみ、ブラウザは正式な XMLHttpRequest リクエストを発行します。それ以外の場合は、エラーが報告されます。

プリフライトリクエストの送信リクエスト:

“预检”请求用的请求方法是OPTIONS,表示这个请求是用来询问的。头信息里面,关键字段是Origin,表示请求来自哪个源。除了Origin字段,”预检”请求的头信息包括两个特殊字段。

  • Access-Control-Request-Method 该字段是必须的,用来列出浏览器的CORS请求会用到哪些HTTP方法,上例是PUT。
  • Access-Control-Request-Headers

    该字段是一个逗号分隔的字符串,指定浏览器CORS请求会额外发送的头信息字段,上例是X-Custom-Header。

    预检请求的返回:

    HTTP/1.1 200 OKDate: Mon, 01 Dec 2008 01:15:39 GMTServer: Apache/2.0.61 (Unix)Access-Control-Allow-Origin: http://api.qiutc.meAccess-Control-Allow-Methods: GET, POST, PUTAccess-Control-Allow-Headers: X-Custom-HeaderContent-Type: text/html; charset=utf-8Content-Encoding: gzipContent-Length: 0Keep-Alive: timeout=2, max=100Connection: Keep-AliveContent-Type: text/plain

  • Access-Control-Allow-Methods必需,它的值是逗号分隔的一个字符串,表明服务器支持的所有跨域请求的方法。注意,返回的是所有支持的方法,而不单是浏览器请求的那个方法。这是为了避免多次”预检”请求。

  • Access-Control-Allow-Headers 如果浏览器请求包括Access-Control-Request-Headers字段,则Access-Control-Allow-Headers字段是必需的。它也是一个逗号分隔的字符串,表明服务器支持的所有头信息字段,不限于浏览器在”预检”中请求的字段。
  • Access-Control-Max-Age 该字段可选,用来指定本次预检请求的有效期,单位为秒。上面结果中,有效期是20天(1728000秒),即允许缓存该条回应1728000秒(即20天),在此期间,不用发出另一条预检请求。

    2)浏览器的正常请求和回应

    一旦服务器通过了”预检”请求,以后每次浏览器正常的CORS请求,就都跟简单请求一样,会有一个Origin头信息字段。服务器的回应,也都会有一个Access-Control-Allow-Origin头信息字段。

参考: 《跨域资源共享 CORS 详解》 http://www.ruanyifeng.com/blog/2016/04/cors.html

)

阮大神的文章,复制粘贴了不少。

2. jsonp

jsonp = json + padding

其实对于常用性来说,jsonp应该是使用最经常的一种跨域方式了,他不受浏览器兼容性的限制。但是他也有他的局限性,只能发送 GET 请求,需要服务端和前端规定好,写法丑陋。

它的原理在于浏览器请求 script 资源不受同源策略限制,并且请求到 script 资源后立即执行。

主要做法是这样的:

  • 在浏览器端:

    首先全局注册一个callback回调函数,记住这个函数名字(比如:resolveJson),这个函数接受一个参数,参数是期望的到的服务端返回数据,函数的具体内容是处理这个数据。

    然后动态生成一个 script 标签,src 为:请求资源的地址+获取函数的字段名+回调函数名称,这里的获取函数的字段名是要和服务端约定好的,是为了让服务端拿到回调函数名称。(如: www.qiute.com?callbackName=resolveJson )。

    function resolveJosn(result) {	console.log(result.name);}var jsonpScript= document.createElement("script");jsonpScript.type = "text/javascript";jsonpScript.src = "http://www.qiute.com?callbackName=resolveJson";document.getElementsByTagName("head")[0].appendChild(jsonpScript);

  • 服务端

    在接受到浏览器端 script 的请求之后,从url的query的callbackName获取到回调函数的名字,例子中是 resolveJson 。

    然后动态生成一段javascript片段去给这个函数传入参数执行这个函数。比如:

    resolveJson({name: 'qiutc'});

  • 执行服务端返回这个 script 之后,浏览器端获取到 script 资源,然后会立即执行这个 javascript,也就是上面那个片段。这样就能根据之前写好的回调函数处理这些数据了。

在一些第三方库往往都会封装jsonp的操作,比如 jQuery 的 $.getJSON 。

3. document.domain

一个页面框架(iframe/frame)之间(父子或同辈),是能够获取到彼此的window对象的,但是这个 window 不能拿到方法和属性(尼玛这有什么用,甩脸)。

// 当前页面域名 http://blog.qiutc.me/a.html<script>function onLoad() { var iframe =document.getElementById('iframe'); var iframeWindow = iframe.contentWindow; // 这里可以获取 iframe 里面 window 对象,但是几乎没用 var doc = iframeWindow.document; // 获取不到}</script><iframe src="http://www.qiutc.me/b.html" onload="onLoad()"</iframe>

这个时候, document.domain 就可以派上用场了,我们只要把 http://blog.qiutc.me/a.html 和 http://www.qiutc.me/b.html 这两个页面的 document.domain 都设成相同的域名就可以了。

前提条件:这两个域名必须属于同一个基础域名!而且所用的协议,端口都要一致。

但要注意的是, document.domain 的设置是有限制的,我们只能把 document.domain 设置成自身或更高一级的父域,且主域必须相同。例如: a.b.example.com 中某个文档的 document.domain 可以设成 a.b.example.com 、 b.example.com 、 example.com 中的任意一个,但是不可以设成 c.a.b.example.com ,因为这是当前域的子域,也不可以设成 baidu.com ,因为主域已经不相同了。

这样我们就可以通过js访问到iframe中的各种属性和对象了。

// 主页面:http://blog.qiutc.me/a.html<script>document.domain = 'qiutc.me';function onLoad() { var iframe =document.getElementById('iframe'); var iframeWindow = iframe.contentWindow; // 这里可以获取 iframe 里面 window 对象并且能得到方法和属性 var doc = iframeWindow.document; // 获取到}</script><iframe src="http://www.qiutc.me/b.html" onload="onLoad()"</iframe>

// iframe 里面的页面<script>document.domain = 'qiutc.me';</script>

4. window.name

window对象有个name属性,该属性有个特征:即在一个窗口(window)的生命周期内,窗口载入的所有的页面都是共享一个 window.name 的,每个页面对 window.name 都有读写的权限, window.name 是持久存在一个窗口载入过的所有页面中的,并不会因新页面的载入而进行重置。

比如有一个 www.qiutc.me/a.html 页面,需要通过a.html页面里的js来获取另一个位于不同域上的页面 www.qiutc.com/data.html 里的数据。

data.html页面里的代码很简单,就是给当前的window.name设置一个a.html页面想要得到的数据值。data.html里的代码:

<script>window.name = '我是被期望得到的数据';</script>

那么在 a.html 页面中,我们怎么把 data.html 页面载入进来呢?显然我们不能直接在 a.html 页面中通过改变 window.location 来载入data.html页面(这简直扯蛋)因为我们想要即使 a.html 页面不跳转也能得到 data.html 里的数据。

答案就是在 a.html 页面中使用一个隐藏的 iframe 来充当一个中间人角色,由 iframe 去获取 data.html 的数据,然后 a.html 再去得到 iframe 获取到的数据。

充当中间人的 iframe 想要获取到 data.html 的通过 window.name 设置的数据,只需要把这个 iframe 的src设为 www.qiutc.com/data.html 就行了。然后 a.html 想要得到 iframe 所获取到的数据,也就是想要得到 iframe 的 window.name 的值,还必须把这个 iframe 的 src 设成跟 a.html 页面同一个域才行,不然根据前面讲的同源策略, a.html 是不能访问到 iframe 里 的window.name 属性的。这就是整个跨域过程。

// a.html<!DOCTYPE html><html lang="en"><head>  <meta charset="UTF-8">  <title>Document</title>  <script> function getData() { var iframe =document.getElementById('iframe'); iframe.onload = function() { var data = iframe.contentWindow.name; // 得到 } iframe.src = 'b.html'; // 这里b和a同源 } </script></head><body>  <iframe src="http://www.qiutc.com/data.html" style="display:none" onload="getData()"</iframe></body></html>

5. HTML5中新引进的window.postMessage

window.postMessage(message, targetOrigin) 方法是html5新引进的特性,可以使用它来向其它的window对象发送消息,无论这个window对象是属于同源或不同源。兼容性:

http://caniuse.com/#search=postMessage

调用postMessage方法的window对象是指要接收消息的那一个window对象,该方法的第一个参数message为要发送的消息,类型只能为字符串;第二个参数targetOrigin用来限定接收消息的那个window对象所在的域,如果不想限定域,可以使用通配符 * 。

需要接收消息的window对象,可是通过监听自身的message事件来获取传过来的消息,消息内容储存在该事件对象的data属性中。

上面所说的向其他window对象发送消息,其实就是指一个页面有几个框架的那种情况,因为每一个框架都有一个window对象。在讨论第种方法的时候,我们说过,不同域的框架间是可以获取到对方的window对象的,虽然没什么用,但是有一个方法是可用的- window.postMessage 。下面看一个简单的示例,有两个页面:

// 主页面  blog.qiutc.com<script>function onLoad() { var iframe =document.getElementById('iframe'); var iframeWindow = iframe.contentWindow; iframeWindow.postMessage("I'm message from main page.");}</script><iframe src="http://www.qiutc.me/b.html" onload="onLoad()"</iframe>

// b 页面<script>window.onmessage = function(e) { e = e || event; console.log(e.data);}</script>

6.CSST (CSS Text Transformation)

一种用 CSS 跨域传输文本的方案。

优点:相比 JSONP 更为安全,不需要执行跨站脚本。

缺点:没有 JSONP 适配广,CSST 依赖支持 CSS3 的浏览器。

原理:通过读取 CSS3 content 属性获取传送内容。

具体可以参考: CSST (CSS Text Transformation)

7.利用flash

flash 嘛,这个东西注定灭亡,不想说了。。。

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