CORS cross-domain analytical principle

Foreword

CORSIn addition is jsonpone of the most common cross-domain than the way, it is also one of the interview will test sites. CORSIs a W3C standard, it stands for "Cross-Origin Resource Sharing" (Cross-origin resource sharing) . It allows the browser to send out across the source server XMLHttpRequestrequests, which overcomes the limitations of AJAX only homologous use. Only use CORSthis cross-domain way for us is not enough. We need to know these to know why.

What is cross-domain

In explaining CORSbefore we must first understand what is cross-domain. Browser security is the cornerstone of the "same origin policy" (same-origin policy). "Homologous" refers to the "three identical":

  • The same protocol
  • The same domain
  • For example the same port:http://www.example.com
http://www.example.com/a.html 同源
http://example.com 域名不同(不同源)
http://www.example.com:8081 端口不同(默认80)
https://www.example.com 协议不同(不同源)
复制代码

The purpose of the same-origin policy: to ensure the security of user information to prevent malicious sites to steal data.

Restriction: If non-homology, a total of three acts is limited.

  • Cookie, LocalStorage, IndexDBCan not be read.
  • DOMImpossible to Get.
  • AJAXRequest can not be sent.

CORS principle of analytic

CORSCross is the source AJAXfundamental solution to the request. JSONPOnly send GETthe request, but CORSallow any type of request.

The entire CORScommunication process is done automatically in the browser, without user involvement. For developers, CORSto communicate with the homologous AJAXno difference in communication, the code is exactly the same. Once AJAX browser cross-origin request, it will automatically add some additional header information, and sometimes more than once additional requests, but users do not have feelings . Therefore, to achieve CORSthe key is communication server. As long as the server implements the CORSinterface, you can communicate across the source.

One or two requests

CORS browser requests into two categories: a simple request (simple request) and requesting non-simple (not-so-simple request). As long as both of the following two conditions belong to a simple request.

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

    HEAD
    GET
    POST
(2)HTTP的头信息不超出以下几种字段:

    Accept
    Accept-Language
    Content-Language
    Last-Event-ID
    Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
复制代码

Who do not meet the above two conditions, it is non-simple request.

Browsers handle both of these requests, it is not the same.

Second, a simple request

  1. The basic procedure for simple requests, the browser makes a direct CORSrequest. Specifically, it is the first information, the addition of a Originfield.

Here is an example of cross-source browser found this AJAXrequest is a simple request, automatically in the header information in to add a Originfield.

GET /cors HTTP/1.1
Origin: http://api.bob.com
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...
复制代码

The above header information, Origina field for describing, which source (port protocol name + +) from this request. Server based on this value, the decision whether to grant the request.

If the Originspecified source, not within the scope of the license, the server returns a normal HTTPresponse. Browser found this response header information does not contain Access-Control-Allow-Originfield (see below), you know wrong, so throw an error, it is XMLHttpRequesta onerrorcallback function to capture. Note that this error code is not recognized by the state, because HTTPthe response status code might be 200.

If the Originresponse to the domain name specified in the license, are returned by the server, a few extra header field.

Access-Control-Allow-Origin: http://api.bob.com
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: FooBar
Content-Type: text/html; charset=utf-8
复制代码

The above header information, the three of CORS request related fields, are to Access-Control-begin with. (1) Access-Control-Allow-OriginThis field is required. Its value is either request Originthe value of the field, either a *, acceptance request any domain.

(2) Access-Control-Allow-CredentialsThis field is optional. Its value is a Boolean value that indicates whether to allow sending Cookie. By default, Cookienot included CORSin the request. It is set true, it means that the server explicit permission, Cookiemay be included in the request sent to the server. This value can only be set trueif the server is not sent by the browser Cookieto the field to delete it.

(3) Access-Control-Expose-HeadersThis field is optional. CORSWhen requested, XMLHttpRequestthe object of getResponseHeader()the method can only get six basic Cache-Controlfields: Content-Language, Content-Type, Expires, Last-Modified, Pragma, . If you want to get the other fields, you must Access-Control-Expose-Headersspecify the inside. Examples of the above specified, getResponseHeader('FooBar')can be returned FooBarvalue of the field.

2, withCredentialsproperty

Speaking of the above, CORSthe request does not send default Cookieand HTTPauthentication information. If you want to Cookiesend to the server, the server agree on the one hand, the specified Access-Control-Allow-Credentialsfield.

Access-Control-Allow-Credentials: true
复制代码

On the other hand, the developer must AJAXopen the request withCredentialsattribute.

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
复制代码

Otherwise, even if the server agree to send Cookie, the browser will not be sent. Alternatively, the server requires setting Cookie, the browser will not be processed.

However, if you omit withCredentialssettings, some browsers will send together Cookie. In this case, it is explicitly closed withCredentials.

xhr.withCredentials = false;
复制代码

Note that, if you want to send Cookie, Access-Control-Allow-Originyou can not set an asterisk, you must specify clear, consistent and domain name requests a web page. At the same time, Cookiestill follow the same-origin policy, only with a domain name server settings Cookiewill upload other domain names Cookiewill not be uploaded and (cross-source) the original page code document.cookiecan not be read under the domain name of the server Cookie.

Third, non-simple request

  1. Preflight request

Non-simple request that there are special requirements for the server request, such as is PUTor DELETE, or Content-Typetype field is application/json.

Non-simple request of the CORSrequest, before the official communication, increase once HTTPqueries, called "preflight" request (preflight).

The browser first asks the server, where the domain of the current web page whether in the license server list, and which can use HTTPverbs and header information fields. Only positive response, the browser will issue a formal XMLHttpRequestrequest, otherwise an error.

The following is a JavaScript script for a browser.

var url = 'http://api.alice.com/cors';
var xhr = new XMLHttpRequest();
xhr.open('PUT', url, true);
xhr.setRequestHeader('X-Custom-Header', 'value');
xhr.send();
复制代码

In the above code, HTTPthe method is requested PUT, and transmitting a custom header information X-Custom-Header.

The browser sees that this is a non-simple request, it automatically sends a "preflight" request to the server can confirm this request. Here is the "preflight" request HTTPheaders.

OPTIONS /cors HTTP/1.1
Origin: http://api.bob.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...
复制代码

Request method "preflight" request is used OPTIONSto indicate that the request is used to query. Head inside information, key segments are Origin, which represents a request from the source. In addition to Originthe fields, the header information "preflight" requests comprises two special fields.

(1) Access-Control-Request-MethodThis field is necessary to list the browser CORSwhich requests will use HTTPthe method, the case is PUT.

(2)Access-Control-Request-Headers

This field is a comma-separated string that specifies the browser CORSrequest extra header field transmitted, the case is X-Custom-Header.

  1. Preflight respond to requests

Server receives a "pre-screening" after the request, examined Origin, Access-Control-Request-Methodand Access-Control-Request-Headersafter field, acknowledge allow cross-origin requests, we can respond.

HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://api.bob.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Content-Length: 0
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain
复制代码

The above HTTPresponse, the key is Access-Control-Allow-Origina field indicating http://api.bob.comcan request data. This field can be set to an asterisk, it agreed any cross-origin requests.

Access-Control-Allow-Origin: *
复制代码

If the browser denied "preflight" request, it returns a normal HTTPresponse, but without any CORSassociated header information field. In this case, the browser will identify the server does not agree preflight request, thus triggering an error, the XMLHttpRequestobject onerrorcaptured callback function. The console will print out the following error message.

XMLHttpRequest cannot load http://api.alice.com.
Origin http://api.bob.com is not allowed by Access-Control-Allow-Origin.
复制代码

Other server responded CORSassociated fields are as follows.

Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 1728000
复制代码

(1) Access-Control-Allow-MethodsThis field is required, its value is a string comma-separated cross-domain requests indicating that all methods that the server supports. Note that the return of all supported methods, rather than simply the method that the browser requests. This is to avoid multiple "preflight" request.

(2) Access-Control-Allow-Headersif the browser request includes Access-Control-Request-Headersa field, the Access-Control-Allow-Headersfield is required. It is also a comma delimited string indicating the server supports all the header field is not limited to a browser request field in the "pre-screening" in.

(3)Access-Control-Allow-Credentials

The same meaning in the field with a simple request.

(4)Access-Control-Max-Age

This field is optional pre-screening is used to specify the current valid request, in seconds. Above results, the period is 20 days (1,728,000 seconds), allowing the cache to respond to the article 1728000 seconds (i.e., 20 days), during which the preflight not issue another request.

  1. Normal request and respond to the browser

Once the server through a "preflight" request, after each normal browser CORSrequest, as it related to a simple request, there will be a Originheader field. Server response, but also will have a Access-Control-Allow-Originheader field.

Here it is after "preflight" request, normal browser CORSrequest.

PUT /cors HTTP/1.1
Origin: http://api.bob.com
Host: api.alice.com
X-Custom-Header: value
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...
复制代码

The above header information Originfield is automatically added to the browser.

The following is a normal server response.

Access-Control-Allow-Origin: http://api.bob.com
Content-Type: text/html; charset=utf-8
复制代码

Head above information, the Access-Control-Allow-Originfield is contained in each response are bound.

And comparison of JSONP

CORSWith JSONPthe same purpose, but than JSONPmore powerful.

JSONPOnly support GETrequest, CORSsupport all types of HTTPrequests. JSONPThe advantage is to support older browsers, and can not support the CORSrequested data website.

Code demonstrates

In the event of cross-domain requests, browser-based console will report the following error:

At this point needs to be set on the server side (nodejs for example)

const http = require('http')
http.createServer(function (request, response) {
    console.log('request come', request.url)
    
    response.writeHead(200, {
      'Access-Control-Allow-Origin': '*'
    })
    response.end('123')
}).listen(8080)

复制代码

Returns the following:

We can see the cross-domain request has been successfully accepted.

Key:

In fact, all we have is not set Access-Control-Allow-Origin: *, the browser will send a request to our server, and receive content returned. When the browser parses found Response Headersno Access-Control-Allow-Origin: *head, and set as the circumstances permit, the browser will request the return of content ignored, and reported cross-domain errors in the command line. This is a feature provided by the browser .

But Access-Control-Allow-Origin: *this set is obviously unsafe because it allows the equivalent of all the domain names, so we can set a specific domain names. For example: Access-Control-Allow-Origin: http://www.baidu.comso that only the http://www.baidu.comdomain name when accessing the browser to function properly resolved .

to sum up

Cross-domain problem is each front-end developer will encounter, cross-domain way there is more than Jsonp, CORSwell postMessage, webScorketetc., when we encounter the problem of cross-domain, quickly locate the problem, know the reason for its occurrence, each of us is an essential quality of the program ape. I hope this article can help you.

Reproduced in: https: //juejin.im/post/5cef28af51882550d41745ea

Guess you like

Origin blog.csdn.net/weixin_34414650/article/details/91468076