Foreword
CORS
In addition is jsonp
one of the most common cross-domain than the way, it is also one of the interview will test sites. CORS
Is 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 XMLHttpRequest
requests, which overcomes the limitations of AJAX only homologous use. Only use CORS
this cross-domain way for us is not enough. We need to know these to know why.
What is cross-domain
In explaining CORS
before 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
,IndexDB
Can not be read.DOM
Impossible to Get.AJAX
Request can not be sent.
CORS principle of analytic
CORS
Cross is the source AJAX
fundamental solution to the request. JSONP
Only send GET
the request, but CORS
allow any type of request.
The entire CORS
communication process is done automatically in the browser, without user involvement. For developers, CORS
to communicate with the homologous AJAX
no 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 CORS
the key is communication server. As long as the server implements the CORS
interface, 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
- The basic procedure for simple requests, the browser makes a direct
CORS
request. Specifically, it is the first information, the addition of aOrigin
field.
Here is an example of cross-source browser found this AJAX
request is a simple request, automatically in the header information in to add a Origin
field.
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, Origin
a 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 Origin
specified source, not within the scope of the license, the server returns a normal HTTP
response. Browser found this response header information does not contain Access-Control-Allow-Origin
field (see below), you know wrong, so throw an error, it is XMLHttpRequest
a onerror
callback function to capture. Note that this error code is not recognized by the state, because HTTP
the response status code might be 200
.
If the Origin
response 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-Origin
This field is required. Its value is either request Origin
the value of the field, either a *
, acceptance request any domain.
(2) Access-Control-Allow-Credentials
This field is optional. Its value is a Boolean value that indicates whether to allow sending Cookie
. By default, Cookie
not included CORS
in the request. It is set true
, it means that the server explicit permission, Cookie
may be included in the request sent to the server. This value can only be set true
if the server is not sent by the browser Cookie
to the field to delete it.
(3) Access-Control-Expose-Headers
This field is optional. CORS
When requested, XMLHttpRequest
the object of getResponseHeader()
the method can only get six basic Cache-Control
fields: Content-Language
, Content-Type
, Expires
, Last-Modified
, Pragma
, . If you want to get the other fields, you must Access-Control-Expose-Headers
specify the inside. Examples of the above specified, getResponseHeader('FooBar')
can be returned FooBar
value of the field.
2, withCredentials
property
Speaking of the above, CORS
the request does not send default Cookie
and HTTP
authentication information. If you want to Cookie
send to the server, the server agree on the one hand, the specified Access-Control-Allow-Credentials
field.
Access-Control-Allow-Credentials: true
复制代码
On the other hand, the developer must AJAX
open the request withCredentials
attribute.
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 withCredentials
settings, 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-Origin
you can not set an asterisk, you must specify clear, consistent and domain name requests a web page. At the same time, Cookie
still follow the same-origin policy, only with a domain name server settings Cookie
will upload other domain names Cookie
will not be uploaded and (cross-source) the original page code document.cookie
can not be read under the domain name of the server Cookie
.
Third, non-simple request
- Preflight request
Non-simple request that there are special requirements for the server request, such as is PUT
or DELETE
, or Content-Type
type field is application/json
.
Non-simple request of the CORS
request, before the official communication, increase once HTTP
queries, 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 HTTP
verbs and header information fields. Only positive response, the browser will issue a formal XMLHttpRequest
request, 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, HTTP
the 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 HTTP
headers.
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 OPTIONS
to 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 Origin
the fields, the header information "preflight" requests comprises two special fields.
(1) Access-Control-Request-Method
This field is necessary to list the browser CORS
which requests will use HTTP
the method, the case is PUT
.
(2)Access-Control-Request-Headers
This field is a comma-separated string that specifies the browser CORS
request extra header field transmitted, the case is X-Custom-Header
.
- Preflight respond to requests
Server receives a "pre-screening" after the request, examined Origin
, Access-Control-Request-Method
and Access-Control-Request-Headers
after 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 HTTP
response, the key is Access-Control-Allow-Origin
a field indicating http://api.bob.com
can 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 HTTP
response, but without any CORS
associated header information field. In this case, the browser will identify the server does not agree preflight request, thus triggering an error, the XMLHttpRequest
object onerror
captured 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 CORS
associated 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-Methods
This 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-Headers
if the browser request includes Access-Control-Request-Headers
a field, the Access-Control-Allow-Headers
field 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.
- Normal request and respond to the browser
Once the server through a "preflight" request, after each normal browser CORS
request, as it related to a simple request, there will be a Origin
header field. Server response, but also will have a Access-Control-Allow-Origin
header field.
Here it is after "preflight" request, normal browser CORS
request.
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 Origin
field 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-Origin
field is contained in each response are bound.
And comparison of JSONP
CORS
With JSONP
the same purpose, but than JSONP
more powerful.
JSONP
Only support GET
request, CORS
support all types of HTTP
requests. JSONP
The advantage is to support older browsers, and can not support the CORS
requested 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 Headers
no 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.com
so that only the http://www.baidu.com
domain 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
, CORS
well postMessage
, webScorket
etc., 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