Heim  >  Artikel  >  Web-Frontend  >  Domänenübergreifende Methoden in js

Domänenübergreifende Methoden in js

小云云
小云云Original
2017-12-09 16:58:241416Durchsuche

Wenn ich einen Oneday-Music-Player erstelle, muss ich Ajax verwenden, um eine Anfrage an die API von Baidu Music zu senden, und dann kann XMLHttpRequest „http://....“ nicht laden. „Zulassen“ wird angezeigt. Der Header „-Origin“ ist auf der Anforderungsressource „http://....“ vorhanden. Bei der Suche wurde festgestellt, dass es sich um ein domänenübergreifendes Problem handelt Ursprungsrichtlinie, also erfahren Sie mehr über domänenübergreifende Wissenspunkte.

Same-Origin-Richtlinie

Die Same-Origin-Richtlinie verhindert, dass aus einer Quelle geladene Dokumente oder Skripte mit Dokumenten oder Skripten aus einer anderen Quelle interagieren ist ein wichtiger Sicherheitsmechanismus zur Isolierung potenziell schädlicher Dateien.

Wenn zwei Seiten dasselbe Protokoll, denselben Port (sofern angegeben) und denselben Domänennamen haben, kann man sagen, dass die beiden Seiten denselben Ursprung haben.

Die folgende Tabelle bezieht sich auf <code><span style="font-size: 14px;">http://store.company.com/dir/page.html</span>http://store.company.com/dir/page.htmlBeispiel für die Erkennung des gleichen Ursprungs:

url 结果 原因
<span style="font-size: 14px;">http://store.company.com/dir2/other.html</span> 成功
<span style="font-size: 14px;">http://store.company.com/dir/inner/other.html</span> 成功
<span style="font-size: 14px;">https://store.company.com/secure.html</span> 失败 不同协议(<span style="font-size: 14px;">https</span><span style="font-size: 14px;">http</span>
<span style="font-size: 14px;">http://store.company.com:81/dir/etc.html</span> 失败 不同端口(81和80)
<span style="font-size: 14px;">http://news.company.com/dir/other.html</span> 失败 不同域名(<span style="font-size: 14px;">news</span><span style="font-size: 14px;">store</span>
url Ergebnis Grund
http://store.company .com/dir2/other.html Erfolg
http://store.company.com/dir/inner/other.html Erfolg
https://store.company.com/secure.html Fehlgeschlagen Verschiedene Protokolle (https und http Code >)
http://store.company.com:81/dir/etc.html Fehlgeschlagen Unterschiedliche Ports (81 und 80)
http://news.company.com/dir/other.html Fehlgeschlagen Verschiedene Domainnamen (News und Store)

Wenn es nicht vom gleichen Ursprung ist, werden drei Verhaltensweisen eingeschränkt:

  • Cookie, LocalStorage und IndexDB können nicht gelesen werden

  • DOM kann nicht abgerufen werden

  • AJAX-Anfrage kann nicht gesendet werden

Same Origin Policy (Cross Domain) vermeiden

Cookie

<span style="font-size: 14px;">document.domain</span>

Cookie ist eine kleine Information, die vom Server an den Browser geschrieben wird und nur von Webseiten im selben Krankenhaus geteilt werden kann. Allerdings sind die Domänennamen der ersten Ebene der beiden Webseiten identisch, die Domänennamen der zweiten Ebene jedoch unterschiedlich. Der Browser ermöglicht die gemeinsame Nutzung von Cookies über <code><span style="font-size: 14px;">document.domain</span>document.domaincode>

Angenommen, ein Skript im Dokument wird unter <code><span style="font-size: 14px;">http://store.company.com/dir/page.html</span><span style="font-size: 14px;">http://store.company.com/dir/ ausgeführt. page.html</span>

Die folgende Aussage:
<span style="font-size: 14px;">document.domain = "company.com"<br></span>

<span style="font-size: 14px;">http://news.company.com/dir/other.html</span>Zu diesem Zeitpunkt http://news .company.com/dir/other.html<span style="font-size: 14px;">http://store.company.com/dir/other.html</span> code>
und http://store.company.com/dir/other.html<span style="font-size: 14px;">document.cookie</span> code> kann

document.cookie übergeben werden, um Cookies, also geteilte Cookies, zu setzen oder abzurufen.

Diese Methode eignet sich jedoch für Cookie- und Iframe-Fenster. LocalStorage und IndexDB können mit dieser Methode nicht dieselbe Ursprungsrichtlinie umgehen.

iframe<span style="font-size: 14px;">iframe</span><span style="font-size: 14px;">window.open</span>Wenn zwei Webseiten unterschiedliche Quellen haben, können sie das DOM der anderen nicht abrufen. Ein typisches Beispiel ist iframe

Fenster und das von der window.open<code><span style="font-size: 14px;">document.domain</span>-Methode geöffnete Fenster, wenn die Quelle unterschiedlich ist Im übergeordneten Fenster wird ein Fehler gemeldet.

Wenn zu diesem Zeitpunkt die Domänennamen der ersten Ebene der beiden Fenster gleich sind, sich aber nur die Domänennamen der zweiten Ebene unterscheiden, legen Sie document.domain

    kann die Same-Origin-Richtlinie umgehen.
  • Für Websites völlig unterschiedlicher Herkunft gibt es derzeit drei Methoden, um das Kommunikationsproblem zwischen domänenübergreifenden Fenstern zu lösen.

  • Fragment-ID

  • Fenstername

Cross-Document Messaging API (Cross-Document Messaging)

<span style="font-size: 14px;">http://store.company.com/dir/other.html#fragment</span>Fragment-ID<span style="font-size: 14px;">#fragment</span>Die Fragment-ID bezieht sich auf den Teil nach # in der URL, also

<p>http://store.company.com/dir/other.html# fragment<span style="font-size: 14px;"></span></p>s <span style="font-size: 14px;">hashchange</span><span style="font-size: 14px;">#fragment</span>(location.hash), wenn nur die Fragment-ID geändert wird, wird die Seitenaktualisierung nicht zurückgesetzt.

Das übergeordnete Fenster kann Informationen in die Fragment-ID des untergeordneten Fensters schreiben, und das untergeordnete Fenster lauscht auf

<span style="font-size: 14px;">Hashchange</span> <span style="font-size: 14px;">window.name</span> Ereignisse werden benachrichtigt.

window.name

Jeder Iframe hat ein Fenster, das ihn umschließt, also natürlich dort Das Attribut window.name bezieht sich auf den Namen des aktuellen Fensters. Das größte Merkmal dieses Attributs ist, dass es unabhängig davon ist, ob es dieselbe Quelle hat oder nicht, solange es sich im selben Fenster befindet. Alle Seiten im Fenster haben Lese- und Schreibberechtigungen für window.name. Der Wert von window.name kann nur in Form einer Zeichenfolge vorliegen. Die maximale Kapazität dieser Zeichenfolge kann je nach Browser etwa 2 MB oder sogar mehr betragen.

例如,想要在<span style="font-size: 14px;">http://example/a.html</span>中获取<span style="font-size: 14px;">http://company.com/data.html</span>中的数据,可以在a.html中使用一个隐藏的iframe,将iframe的src首先设置为<span style="font-size: 14px;">http://company.com/data.html</span>,将其window.name设置为所需的数据内容,随后再将这个iframe的src设置为跟a.html页面同一个域的一个页面,不然a.html获取不到该iframe的window.name

<span style="font-size: 14px;">window.postMessage</span>

这是html5中新引入的一个API,可以使用它向其它的window对象发送消息,无论这个window对象属于同源还是不同源。

例如,父窗口<span style="font-size: 14px;">http://example/a.html</span>向子窗口<span style="font-size: 14px;">http://company.com/data.html</span>发送消息:

<span style="font-size: 14px;">var newWin = window.open('http://company.com/data.html', 'title')<br>newWin.postMessage('Hello World!'. 'http://company.com/data.html')<br></span>

<span style="font-size: 14px;">window.postMessage</span>方法的第一个参数是具体的信息内容,第二个参数是接收消息的窗口的源,即<span style="font-size: 14px;">协议</span>+<span style="font-size: 14px;">端口</span>+<span style="font-size: 14px;">域名</span>,也可以设置为<span style="font-size: 14px;">*</span>,表示不限制域名。

子窗口向父窗口发送消息的写法类似:

<span style="font-size: 14px;">window.opener.postMessage('Nice to see you', 'http://example/a.html')<br></span>

子窗口和父窗口都可以通过<span style="font-size: 14px;">message</span>时间,监听对方的消息。

<span style="font-size: 14px;">window.addEventListener('message', function(e) {<br>    // ...<br>}, false)<br></span>

<span style="font-size: 14px;">message</span>事件的事件对象<span style="font-size: 14px;">event</span>有以下三个属性:

  • event.source: 发送消息的窗口

  • event.origin: 消息发向的网址(可以限制目标网址)

  • event.data: 消息内容

通过<span style="font-size: 14px;">window.postMessage</span>,也可以读写其他窗口的<span style="font-size: 14px;">localStorage</span>

AJAX

同源策略规定,AJAX请求只能发给同源的网址,否则就报错,但是有三种方法可以规避这个限定:

  • JSONP

  • WebSocket

  • CORS

JSONP

JSONP是服务器与客户端跨源通信的常用方法。基本思想是利用<span style="font-size: 14px;"><script></span>请求脚本能够跨域访问的特性,先定义了一个回调方法,然后将其作为url参数的一部分发送到服务端,服务端通过字符串拼接的方式将数据包裹在回调方法中,再返回回来。

<span style="font-size: 14px;">// 网页动态插入`<script>`元素<br>function addScriptTag(src) {<br>    var script = document.createElement("script")<br>    script.setAttribute("type", "text/javascript")<br>    srcipt.src = src<br>    document.body.appendChild(script)<br>}<br><br>window.onload = function() {<br>    addScriptTag('http://example.com/ip?callback=foo')<br>}<br><br>function foo(data) {<br>    // ...<br>}<br></span>

WebSocket

WebSocket是一种通信协议,使用<span style="font-size: 14px;">ws://</span>(非加密)和<span style="font-size: 14px;">wss://</span>(加密)作为协议前缀。该协议不实行同源政策,只要服务支持,就可以通过它进行跨源通信。

浏览器发出的WebSocket请求的头信息中含有<span style="font-size: 14px;">Origin</span>字段,表示该请求的请求源,即发自哪个域名。(加入白名单)

CORS

跨域资源共享(Cross-Origin Resource Sharing,CORS)是一种使用额外的HTTP头来使一个用户代理从一个不同于当前站点(域)的服务器获取指定的资源的机制。用户代理使用跨域HTTP请求来获取与当前文档不同域、不用协议或端口的资源。

出于安全考虑,浏览器会限制从脚本内发起的跨域HTTP请求。而跨域资源共享(CORS)机制允许web应用服务器进行跨域访问控制,从而使跨域数据传输得以安全进行。浏览器支持在API容器中(例如<span style="font-size: 14px;">XMLHttpRequest</span><span style="font-size: 14px;">Fetch</span>)使用CORS,以降低跨域HTTP请求所带来的风险。

跨域资源共享标准允许在下列场景中使用跨域HTTP请求:

  • 由XMLHttpRequest或Fetch发起的跨域HTTP请求;

  • web字体(CSS中通过<span style="font-size: 14px;">@font-face</span>使用跨域字体资源),因此,网站就可以发布TrueType字体资源,并只允许已授权网站进行跨站调用;

  • WebGL贴图;

  • 使用drawImage将Images/video画面绘制到canvas;

  • 样式表(使用CSSOM);

  • Scripts(未处理的异常)。

浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)

只要同时满足以下两大条件,就属于简单请求:

1 请求方法是以下三种方法之一:

<span style="font-size: 14px;">- HEAD<br>- GET<br>- POST<br></span>

2 HTTP的头信息不超出以下几种字段:

<span style="font-size: 14px;">- Accept<br>- Accept-Language<br>- Content-Language<br>- Last-Event-ID<br>- Content-Type:(只限三个值:application/x-www-form-urlencoded、multipart/from-data、text/plain)<br></span>

只要不同时满足上面两个条件,就属于非简单请求

简单请求

对于简单请求,浏览器会在请求头部增加一个<span style="font-size: 14px;">Origin</span>字段。这个字段用来说明本次请求来自哪个源(协议+域名+端口)。服务器根据这个值决定是否同意这次请求。

如果<span style="font-size: 14px;">Origin</span>指定的源不在许可范围内,服务器会返回一个正常的HTTP回应。而这个回应的头信息不包含<span style="font-size: 14px;">Access-Control-Allow-Origin</span>字段,从而会抛出错误被<span style="font-size: 14px;">XMLHttpRequest</span><span style="font-size: 14px;">onerror</span>函数捕获,(回应的状态码有可能是200)。

如果<span style="font-size: 14px;">Origin</span>指定的域名在许可范围内,服务器返回的响应,会多出几个头信息字段

<span style="font-size: 14px;">Access-Control-Allow-Origin: ...<br>Access-Control-Allow-Credentials: true<br>Access-Control-Expose-Headers: callback<br>Content-Type: text/html; charset=utf-8<br></span>
  • <span style="font-size: 14px;">Access-Control-Allow-Origin</span>: 必须。值要么是请求时<span style="font-size: 14px;">Origin</span>的值,要么是'*'

  • <span style="font-size: 14px;">Access-Control-Allow-Credentials</span>: 可选。布尔值,决定是否允许发送Cookie,不需要则删除该字段。

  • <span style="font-size: 14px;">Access-Control-Expose-Headers</span>: 可选。CORS请求时,<span style="font-size: 14px;">XMLHttpRequest</span>对象的 <span style="font-size: 14px;">getResponseHeader()</span>方法只能拿到6个基本字段:<span style="font-size: 14px;">Cache-Control</span><span style="font-size: 14px;">Content-Language</span><span style="font-size: 14px;">Content-Type</span><span style="font-size: 14px;">Expires</span><span style="font-size: 14px;">Last-Modified</span><span style="font-size: 14px;">Pragma</span>。如果想拿到其他字段,就需要在<span style="font-size: 14px;">Access-Control-Expose-Header</span>里面指定。上面的例子指定为callback,则可以使用<span style="font-size: 14px;">getResponseHeader(callback)</span>获取callback字段的值。

CORS请求默认不发送Cookie和HTTP认证信息。如果要把Cookie发送到服务器,一方面要服务器同意,指定<span style="font-size: 14px;">Access-Control-Allow-Credentials</span>字段,另一方面,开发者需要在AJAX请求中设置<span style="font-size: 14px;">withCredentials</span>属性:

<span style="font-size: 14px;">var xhr = new XMLHttpRequest()<br>xhr.withCredentials = true<br></span>

否则,即使服务器同意发送Cookie,浏览器也不会发送。

需要注意的是,如果要发送Cookie,<span style="font-size: 14px;">Access-Control-Allow-Origin</span>就不能设为星号,必须指定明确的、与请求网页一致的域名。同时,Cookie依然遵循同源策略,只有用服务器域名设置的Cookie才会上传,其他域名的Cookie并不会上传,且跨域的原网页中的<span style="font-size: 14px;">document.cookie</span>操作也无法获取嗷服务器域名下的Cookie。

非简单请求

非简单请求是那种对服务器有特殊要求的请求,比如请求方法是<span style="font-size: 14px;">PUT</span><span style="font-size: 14px;">DELETE</span>,或者<span style="font-size: 14px;">Content-Type</span>字段的类型是<span style="font-size: 14px;">application/json</span>

非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为“预检”请求。

浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP操作和头信息字段。只有得到肯定答复,浏览器才会发出正式的<span style="font-size: 14px;">XMLHttpRequest</span>请求,否则就报错。

“预检”请求用请求方法是<span style="font-size: 14px;">OPTIONS</span>,表示这个请求是用来询问的。头信息里面,关键字段是<span style="font-size: 14px;">Origin</span>,表示请求来自哪个源。

还有以下两个特殊字段:

  • <span style="font-size: 14px;">Access-Control-Request-Method</span>: 必须。列出非简单请求的请求类型

  • <span style="font-size: 14px;">Access-Control-Request-Headers</span>: 非简单请求额外携带的头信息字段。

服务器返回的响应:

<span style="font-size: 14px;">Access-Control-Allow-Methods: ...<br>Access-Control-Expose-Headers: callback<br>Access-Control-Allow-Credentials: true<br>Access-Control-Max-Age: 1728000<br></span>
  • Access-Control-Allow-Methods: 必须。逗号分隔的一个字符串,表明服务器支持的所有跨域请求的方法。为了避免多次“预检”行为。

  • Access-Control-Expose-Headers: Wenn die Browseranforderung <span style="font-size: 14px;">Access-Control-Request-Headers</span>Access-Control-Request-Headers Feld ist das Feld <code><span style="font-size: 14px;">Access-Control-Allow-Headers</span>Access-Control-Allow-Headers erforderlich. Es handelt sich außerdem um eine durch Kommas getrennte Zeichenfolge, die alle vom Server unterstützten Header-Felder angibt und nicht auf die vom Browser im „Preflight“ angeforderten Felder beschränkt ist.

  • Access-Control-Allow-Credentials: hat die gleiche Bedeutung wie eine einfache Anfrage.

  • Access-Control-Max-Age: Der Gültigkeitszeitraum dieser Preflight-Anfrage.

Vergleich von CORS und JSONP

CORS hat den gleichen Zweck wie JSONP, ist aber leistungsfähiger als JSONP.

JSONP unterstützt nur <span style="font-size: 14px;">GET</span><span style="font-size: 14px;">GET</span>

-Anfragen, CORS unterstützt alle Arten von HTTP-Anfragen. Der Vorteil von JSONP besteht darin, dass es ältere Browser unterstützt und Daten von Websites anfordern kann, die CORS nicht unterstützen.

Verwandte Empfehlungen:

Schritte zur Implementierung von Lazy Loading und Cross-Domain mit Js

Wie man Js domänenübergreifend versteht

Detaillierte Erklärung, wie man die domänenübergreifende Funktion von Laravel aktiviert

Das obige ist der detaillierte Inhalt vonDomänenübergreifende Methoden in js. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn