Heim  >  Artikel  >  Web-Frontend  >  AJAX-Prinzipien und domänenübergreifende CORS-Methoden

AJAX-Prinzipien und domänenübergreifende CORS-Methoden

一个新手
一个新手Original
2017-10-25 14:24:384794Durchsuche

Ajax ist eine der grundlegenden Funktionen, die für die Front-End-Entwicklung erforderlich sind. Sie können es verwenden, aber Sie verstehen möglicherweise nicht unbedingt seine Prinzipien und tiefergehende Kenntnisse im Zusammenhang mit der Serverkommunikation. In den letzten zwei Tagen habe ich viele Artikel gelesen und festgestellt, dass meine Back-End-Fähigkeiten meine Erkundung von Wissensbereichen im Zusammenhang mit der Netzwerkkommunikation eingeschränkt haben und ich meine Mängel so schnell wie möglich ausgleichen sollte.

Lassen Sie uns über ajax verwandte Dinge sprechen, einschließlich eines Teils von xhr/xdr/ajax/cors/http, der einige veraltete historische Ballaststoffe wie IE6/7 usw. verwirft.

Die Entstehung von Ajax

Im Jahr 2005 schlug Jesse James Garrett die Ajax-Technologie vor, die Asynchronous Javascript and XML heißt. Der Kern von Ajax ist das XMLHttpRequest-Objekt, das kurz: Dadurch kann der Browser zusätzliche Daten vom Server anfordern, ohne die Seite zu entladen, was das Benutzererlebnis erheblich verbessert. Zuvor existierte diese Technologie tatsächlich und wurde von einigen Leuten implementiert, sie war jedoch nicht beliebt und wurde von Browsern nicht unterstützt. Danach führte IE5 jedoch erstmals das XHR-Objekt ein und unterstützte die XHR-Technologie, die anschließend von allen Browsern unterstützt wurde. ajax

Objekte und Anfragen XMLHttpRequest

ist eine API, die dem Client die Funktion der Kommunikation zwischen dem Server und dem Client bereitstellt, ohne die Seite zu aktualisieren. Es kann nicht nur Daten vom Typ XML abrufen, sondern alle Arten von Daten. Zusätzlich zum HTTP-Protokoll werden auch Datei- und FTP-Protokolle unterstützt. Wir können ein neues XHR-Objekt über seinen Konstruktor erstellen. Dieser Vorgang muss vor allen anderen Vorgängen abgeschlossen werden: XHR

var xhr = new XMLHttpRequest();
Wir können die Prototypenkette von

leicht über die Konsole sehen:XHR. Es verfügt über Methoden und Attribute in der Prototypenkette und sich selbst. Werfen wir nun einen Blick auf unsere häufig verwendeten Methoden: Object -> EventTarget -> XMLHttpRequestEventTarget -> XMLHttpRequest
AJAX-Prinzipien und domänenübergreifende CORS-Methoden

Lassen Sie uns einige seiner Hauptmethoden erklären Wenn Sie ein neues xhr-Objekt erstellen, müssen Sie zunächst dessen

-Methode aufrufen: open()

// 第一个参数可以为get/post等,表示该请求的类型
// 第二个参数是请求的url,可以为相对路径或绝对路径
// 第三个参数代表是否异步,为true时异步,为false时同步
// 第四五个参数为可选的授权使用的参数,因为安全性不推荐明文使用
xhr.open('get', 'example.php', true, username, password);
Betrifft hier die Same-Origin-Richtlinie. Wenn die zweite Parameter-URL domänenübergreifend ist, wird sie von blockiert Browser Einen Sicherheitsfehler melden. Die Same-Origin-Richtlinie bedeutet, dass das Protokoll, der Domänenname und der Port der aktuellen Seite und der Ziel-URL identisch sind. Wie später erwähnt wird, implementieren andere Browser als der IE domänenübergreifende Anforderungen über XHR-Objekte. Legen Sie die URL einfach auf eine absolute URL fest.

Wenn die Initialisierungsanforderung abgeschlossen ist, rufen wir die Methode

auf, um die Anforderung zu senden: send()

var data = new FormData();
data.append('name', 'Nicholas');
// 接受一个请求主体发送的数据,如果不需要,传入null
xhr.send(data);
Wenn der Anforderungstyp

ist, werden die Parameter von send() verwendet ignoriert und zugeordnet werden Ist null, die von send() übergebenen Parameter wirken sich auf den Standardwert unseres Anforderungsheaders aus. get/head Dieses Feld stellt den Typ des zurückgegebenen Ressourceninhalts dar und wird für die Browserverarbeitung verwendet In einigen Szenarien führt das Durchsuchen des Servers MIME-Sniffing durch, um festzustellen, wie mit der zurückgegebenen Ressource umgegangen wird. content-type

definiert

-Daten in XHR2级, die für die Serialisierung allgemeiner Formulardaten verwendet werden: FormData

// 直接传入表单id
var data = new FormData(document.getElementById('user-form'));

// 创建类表单数据
var data = new FormData();
data.append('name', 'Nicholas');

// `FormData`可以直接被send()调用,会自动修改xhr的content-type头部
xhr.send(data);

// 请求头部的content-type: multipart/form-data; boundary=----WebKitFormBoundaryjn3q2KKRYrEH55Vz

// 请求的上传数据 Request Payload:
------WebKitFormBoundaryjn3q2KKRYrEH55Vz
Content-Disposition: form-data; name="name"

Nicholas
------WebKitFormBoundaryjn3q2KKRYrEH55Vz--

Zu den häufig verwendeten Methoden gehört FormData, beide häufig verwendeten Methoden sind ähnlich zu Arrays wird nicht noch einmal erklärt. append/delete/entries/forEach/get/getAll/has/keys/set/values

Anfragemethode

ist der häufigste Anfragetyp, der am Ende der URL hinzugefügt werden kann. Für XHR muss jeder Schlüssel korrekt codiert sein -Wert-Paare müssen mit GET codiert werden, und Schlüssel-Wert-Paare werden durch encodeURIComponent() getrennt: &

// 封装序列化键值对
function addURLParam(url, name, value) {
    url += (url.indexOf('?') === -1 ? '?' : '&';
    url += encodeURIComponent(name) + '=' + encodeURIComponent(value);
    return url;
}

Die Anforderungshäufigkeit ist nach der POST-Anfrage an zweiter Stelle und wird normalerweise gesendet Weitere Daten und das Format sind nicht begrenzt. Die Daten werden als Parameter an GET übergeben. send()

HTTP bietet insgesamt neun Anforderungsmethoden. Jedes Verb stellt eine andere Semantik dar, aber nur die beiden oben genannten werden häufig verwendet:

 - OPTIONS:返回服务器针对特定资源所支持的HTTP请求方法。也可以利用向Web服务器发送'*'的请求来测试服务器的功能性。 
 - HEAD:向服务器索要与GET请求相一致的响应,只不过响应体将不会被返回。这一方法可以在不必传输整个响应内容的情况下,就可以获取包含在响应消息头中的元信息。 
 - GET:向特定的资源发出请求。 
 - POST:向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的创建和/或已有资源的修改。 
 - PUT:向指定资源位置上传其最新内容。 
 - DELETE:请求服务器删除Request-URI所标识的资源。 
 - TRACE:回显服务器收到的请求,主要用于测试或诊断。 
 - CONNECT:HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。
 - PATCH: 用于对资源进行部分修改
HTTP-Header-Informationen

Alle HTTP-Anforderungen und -Antworten enthalten Header-Informationen, und das xhr-Objekt ermöglicht es uns, einige der Header-Informationen zu manipulieren. Mit der Methode

können wir benutzerdefinierte Header-Informationen festlegen oder die standardmäßigen normalen Header-Informationen des Browsers ändern. Häufig verwendete Anforderungsheader: xhr.setRequestHeader()

// 下面的实例是从我本地的一次请求取出的

Accept: 浏览器能够处理的内容类型。// */*
Accept-Charset: 浏览器能够显示的字符集。// 未取到
Accept-Encoding: 浏览器能够处理的压缩编码。// gzip,deflate
Accept-Language: 浏览器当前设置的语言。// zh-CN,zh;q=0.8,en;q=0.6
Connection: 浏览器与服务器之间连接的类型。// keep-alive
Cookie: 当前页面设置的任意Cookie。// JlogDataSource=jomodb
Host: 发出请求的页面所在域。// gzhxy-cdn-oss-06.gzhxy.baidu.com:8090
Referer: 发出请求的页面URI。// http://gzhxy-cdn-oss-06.gzhxy.baidu.com:8090/jomocha/index.php?r=tools/offline/index
User-Agent: 浏览器的用户代理字符串。// Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36
Wir ändern im Allgemeinen nicht die normalen Browser-Header-Informationen, was sich auf die Serverantwort auswirken kann. Bei Bedarf kann es über

geändert werden: xhr.setRequestHeader()

// 传入头部键值对,键值不区分大小写,如果多次设置,则追加
// 此时请求头部的content-type: application/json, text/html
xhr.setRequestHeader('content-type', 'application/json');
xhr.setRequestHeader('content-type', 'application/json');
Das Festlegen der Header-Informationen muss nach

und vor open() aufgerufen werden. Die Antwort-Header-Informationen werden im Backend verarbeitet und werden hier nicht erläutert. Einige Anforderungsheaderinformationen dürfen nicht festgelegt werden, z. B. send() usw. Accept-Encoding, Cookie

Nachdem die Anfrage zurückgegeben wurde, können wir den Antwortheader erhalten:

// 获取指定项的响应头
xhr.getResponseHeader('content-type'); // application/json;charset=utf-8
// 获取所有的响应头部信息
xhr.getAllResponseHeaders();
Hier ist eine kurze Erläuterung des Inhaltstypwerts, der sich auf den HTTP-Inhaltstyp der Anfrage bezieht Antwort, die sich darauf auswirkt, wie der Server und der Browser Daten verarbeiten. Der Standardwert ist

, häufig verwendete sind: text/html

// 包含资源类型,字符编码, 边界字符串三个参数,可选填

text/html;charset=utf-8    // html标签文本
text/plain    // 纯文本
text/css    // css文件
text/javascript    // js文件
// 普通的表单数据,可以通过表单标签的enctype属性指定
application/x-www-form-urlencode
// 发送文件的POST包,包过大需要分片时使用`boundary`属性分割数据作边界
multipart/form-data; boundary=something
// json数据格式
application/json
// xml类型的标记语言
application/xml

XHR对象的响应

我们现在对请求的发起很了解了,接着看下如何拿到响应数据。如果我们给open()传递的第三个参数是true,则代表为同步请求,那么js会被阻塞直到拿到响应,而如果为false则是异步请求,我们只需要绑定xhr.onreadystatechange()事件监听响应即可。最上面的图已经说明了readystate的值含义,所以我们可以:

// xhr v1 的写法,检测readystate的值,为4则说明数据准备完毕,需要在open()前定义
xhr.onreadystatechange = function () {
    if (xhr.readyState === 4) {
        if (xhr.status === 200 || xhr.status === 304) {
            console.log(xhr.responseText);
        } else {
            console.log(xhr.statusText);
        }
    }   
}

// xhr v2 的写法,onload()事件说明数据准备完毕
xhr.onload = function () {
    if (xhr.status === 200 || xhr.status === 304) {
        console.log(xhr.responseText);
    } else {
        console.log(xhr.statusText);
    }
}

xhr对象的响应数据中包含几个属性:

response    // 响应的数据
responseURL    // 发起响应的URL
responseType    // 响应的类型,用于浏览器强行重置响应数据的类型
responseText    // 如果为普通文本,则在这显示
responseXML    // 如果为xml类型文本,在这里显示

数据会出现在responseText/responseXML中的哪一个,取决于服务器返回的MIME类型,当然我们也有一些方式在浏览器端设置如何处理这些数据:

// xhr v1 的写法,设置响应资源的处理类型
xhr.overrideMimeType('text/xml');

// xhr v2 的写法, 可用值为 arraybuffer/blob/document/json/text
xhr.responseType = 'document';

响应数据相关的属性默认为null / '',只有当请求完成并被正确解析的时候才会有值,取决于responseType的值,来确定response/responseText/responseXML谁最终具有值。

XHR的高级功能

xhr v2里提供了超时和进度事件。

超时

xhr.timeout = 1000;    // 1分钟,单位为ms
xhr.ontimeout = function () {};

在请求send()之后开始计时,等待timeout时长后,如果没有收到响应,则触发ontimeout()事件,超时会将readystate=4,直接触发onreadystatechange()事件。

请求进度

像上图所示,xhr v2定义了不同的进度事件:loadstart/progress/error/abort/load/loadend,这其中我们已经说过了onload()事件为内容加载完成可用。现在说一下onprogress()进度事件:

xhr.onprogress = function (event) {
    if (event.lengthComputable) {
        console.log(event.loaded / event.total);
    }
}

该事件会接收一个event对象,其target属性为该xhr对象,lengthComputable属性为total size是否已知,即是否可用进度信息,loaded属性为已经接收的字节数,total为总字节数。该事件会在数据接收期间不断触发,但间隔不确定。

跨域CORS

提到XHR对象,我们就会讲到跨域问题,它是为了预防某些恶意行为的安全策略,但有时候我们需要跨域来实现某些功能。需要注意的是跨域并不仅仅是前端单方面的事情,它需要后端代码进行配合,我们只是通过一些方式跳过了浏览器的阻拦。

对那些可能对服务器数据产生副作用的 HTTP 请求方法(特别是 GET 以外的 HTTP 请求,或者搭配某些 MIME 类型的 POST 请求),浏览器必须首先使用 OPTIONS 方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨域请求。服务器确认允许之后,才发起实际的 HTTP 请求。

CORS(Cross-Origin Resource Sharing, 跨域资源共享)的思想是浏览器和服务端通过头部信息来进行沟通确认是否给予响应。如:

Origin: http://www.baidu.com    // 浏览器的头部信息

// 如果服务端认可这个域名的跨域请求,如下设置就可跨域访问资源
Access-Control-Allow-Origin: http://www.baidu.com

如上就可以实现最简单的跨域访问,但是此时不能携带任何的cookie,如果我们需要传递cookie进行身份认证,需要设置:

xhr.withCredentials = true;    // 浏览器端
Access-Control-Allow-Credentials: true;    // 服务端

这样我们就可以传递认证信息了,但如果允许认证,Access-Control-Allow-Origin不能设置为*,而一定是具体的域名信息。

现在的浏览器都对CORS有了实现,如IE使用XDomainRequest对象,其它浏览器使用XMLHttpRequest对象。所以在此之前有很多奇技淫巧,如通过jsonp/图像 Ping方法都不再详述,而且其都需要服务端配合并且有很多局限性。

IE实现: XDomainRequest

var xdr = new XDomainRequest();
xdr.open('get', 'http://www.site.com/page');
xdr.send(null);

XDR区别于普通XHR:

  • 不能传输cookie

  • 只能设置请求头部的content-type

  • 不能访问响应头部信息

  • 只支持get/post方法

通过这些区别可以阻止一部分的CSRF(Cross-Site Request Forgery,跨站点请求伪造)XSS(Cross-Site Scripting,跨站点脚本)

XDR与XHR的使用上非常相似,区别有几点:

  • open()方法只接受两个参数,请求类型和URL

  • 只允许异步请求

  • 响应完成触发onload()事件,但我们只能访问responseText原始文本,并且无法获取响应的status.

  • 异常事件都会触发error事件,并且无错误信息可用。

其余浏览器实现: XMLHttpRequest

其余浏览器通过XHR对象直接实现了CORS,你只需要做的就是open()方法中传入一个绝对URL。

xhr.open('get', 'http://www.site.com/page', true);

相对于普通的XHR对象,CORS-XHR依然有部分限制:

  • 不能使用setRequestHeader()定义头部

  • 不能传递cookie

  • 调用getAllResponseHeaders(),结果为空

其余跨域方法

上面的两种方法已经很成熟了,但是仍然有一部分方法可以跨域,比如图像Ping

var img = new Image();
img.onload = img.onerror = function () {
    console.log('done');
}
img.src = 'http://www.site.com/test?name=Nicholas';

这种方式常用于服务端统计广告的点击次数,其缺陷为:

  • 只能是GET请求

  • 单向通信,无法获取响应文本

另外还有JSONP

function handleResponse(response) {
    console.log(response.ip, response.city);
}

var script = document.createElement('script');
script.src = 'http://freegeoip.net/json?callback=handleResponse';
document.body.insertBefore(script, document.body.firstChild);

这种方式通过和服务器配合,跨域请求一个js文件并被服务器处理后传回:

handleResponse({'name': 'Nicholas'});

然后直接在浏览器调用了该函数,传回的数据被当做response形参进行处理。但它也有一些缺陷:

  • 访问的方式是请求js,所以如果域名不安全,则很容易被恶意代码直接执行并攻击

  • 无法检测是否错误,因为js不支持这样的接口事件,只能超时判断

上面两种方式很容易看出,我们在支持CORS之前,使用的方法只不过是采用img/css/js等不受跨域访问限制的对象,变相拿到了响应数据,但都有缺陷,所以如果没有历史包袱,建议采用XDR或XHR对象来实现跨域访问。

XHR的兼容性

我们可以直接到Can I use这个网站上查询兼容性问题:
AJAX-Prinzipien und domänenübergreifende CORS-Methoden


Das obige ist der detaillierte Inhalt vonAJAX-Prinzipien und domänenübergreifende CORS-Methoden. 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