Cross-domain, or cross-domain resource sharing – Cross-Origin Resource Sharing, is a W3C standard that allows browsers to issue XMLHttpRequest requests to non-same-origin servers.
What is a non-same-origin server? The definition of homology is that the protocol (HTTP/HTTPS), port(omitted port 80 / other digital port), and host (a.website.com/b.website.com/c.com) of two urls are the same. If the protocol, port, and host are different, they are non-identical.
The browser itself does not allow cross-domain resource requests, in order to ensure that each site’s user information — usually stored in cookies — cannot be accessed by other sites. Currently, in addition to cookies, localStorage and IndexDB cannot be accessed across domains. Information security is guaranteed by a strict policy that DOM cannot be fetched across domains and Ajax requests cannot be sent across domains.
But in practice, we often use the mode of front and back end separation for development, cross-domain request is inevitable, under the development mode, the same origin policy of the browser brings a lot of inconvenience.
What solutions do we have to solve the problem caused by the same origin policy?
Set up the document. The domain
In this case, the level 1 domain name is the same as the online domain name, but the level 2 domain name is not the same. What if the local request can carry the cookies of the online environment?
Can be achieved by
document.domain = 'myhostname'
Copy the code
In subsequent same-origin checks, this setting will tell the browser that the current page wants to be allowed to read the cookie of the top-level domain name.
Now, the domain name check has passed, but usually we will use a port number in the development environment, such as 8080, 3001, etc. The port number is checked by the browser separately, after setting document.domain, the port number will be overwritten to NULL, and the online domain is not NULL.
So we usually use document.domain assignments in a way that allows cross domains, but also in the parent domain
document.domain = 'myhostname'
Copy the code
In this way, the host and port can be consistent.
This method only works for cookie reading and iframe Windows.
In a more general cookie sharing mode, when the server sets the cookie, it specifies the domain name of the cookie as.myhostname, for example:
Set-Cookie: key=value; domain=.example.com; .Copy the code
postMessage
In order to solve iframe cross-domain messaging, HTML5 introduces an API — Cross-document Messaging API.
Before this, people might have used window.name to pass messages in non-homologous pages, which was a hack.
With the new API, we can use it in a single page:
Window. PostMessage (' info 'target) / / parent window to the iframe window. The opener. PostMessage (' info' target) / / child window to the parent windowCopy the code
To send a message in the target page using:
Window.addeventlistener ('message', function(event) {function(event) {function(event) { Avoid receiving unsafe messages from other sources console.log(event.data, event.origin, event.source); },false);Copy the code
Listen for messages.
With this API, we can pass not only simple information to iframe, but also complex message objects, so that localStorage information can also be shared.
CORS
Ajax requests can only be sent to same-origin urls. We can use proxies to bypass the same-origin policy, or we can use CORS to bypass the same-origin restriction.
CORS here is a mechanism to tell the browser that some HTTP requests can access cross-domain resources by using additional HTTP header information.
The entire CORS communication process is automatically completed by the browser, and the user will not be aware of it. As soon as the browser discovers that an Ajax request crosses domains, it automatically adds some additional header information, and sometimes an additional request.
Non-simple request
For example, we often see an Options-type HTTP method in everyday development. This is because in CORS, when faced with a non-simple request, the browser will first use the OPTIONS method to initiate a pre-check request to check whether the actual request can be accepted by the server. The precheck request header information usually has:
OPTIONS /resources/post-here/ HTTP/1.1
Origin: http://foo.example
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type
Copy the code
After receiving the request, it will judge whether to accept the following actual request according to the request header information. If yes, it will return the corresponding:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://foo.example
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: Content-Type
Copy the code
If rejected, the browser will return a normal HTTP response without any CORS related header fields. The browser will print a Red Cross – domain error.
Note that the implementation of CORS requires both browser and server support, but the key is the server.
Non-simple requests were mentioned above. Browsers divide requests into two categories, simple and non-simple, and we can recognize non-simple requests as long as we can distinguish simple requests.
A simple request
It is a simple request as long as the following two conditions are met:
-
The request method is one of HEAD, GET, and POST
-
The header information does not exceed the following range:
Accept accept-language content-language last-event-id content-type: Only application/ X-www-form-urlencoded, multipart/form-data, Text /plainCopy the code
For simple cross-domain requests, the browser does not send OPTIONS precheck requests, but simply adds the Origin field to the header information.
If Origin specifies a domain name that is allowed by the server, the response will return several more fields:
Access-Control-Allow-Origin: somehost
Access-Control-Allow-Credentials: true
Content-Type: text/html; charset=utf-8
Copy the code
In CORS requests, the getResponseHeader() method of the XMLHttpRequest object takes only six basic fields: Cache-control, Content-language, Content-Type, Expires, Last-Modified, Pragma. If you want to get other fields, you must specify access-Control-expose-headers:
Access-Control-Expose-Headers: X-xxxx
Copy the code
Cookies carry
Note that CORS requests do not send cookies by default. If cookies are to be sent, on the one hand the server needs to specify:
Access-Control-Allow-Credentials: true
Copy the code
On the other hand, ajax requests, such as the fetch header, need to set:
withCredentials: true
Copy the code
JSONP
JSONP is a simple method that works well with browsers. The basic idea is to add a Script tag to a web page and ask the server for JSON data. When the server receives the request, the data will be sent back in a named callback function.
The reason for this is that loading of JS resources is not restricted by the same origin policy.
In addition to Js resources, the following resource types are also not restricted by the same origin policy:
<link rel="stylesheet" href="..." > Images displayed via <img> multimedia resources played via <video> and <audio> Fonts introduced via @font-face via plugins embedded in <object>, <embed> and <applet> Any resource loaded with <iframe>.Copy the code
A random string is used to define the name of the callback function.
Such as:
function addScript(src) { var script = document.createElement('script') script.setAttribute("type","text/javascript") script.src = src document.body.appendChild(script) } window.onload = function () { addScript('http://hostname/api? callback=myCallbackFunc') } function myCallbackFunc(data) { console.log(data) }Copy the code
When the server receives the request, it puts the data in the argument of the callback function and returns:
myCallbackFunc({ ... some props });Copy the code
Since the script element requests a script that runs directly as code, the myCallbackFunc function is called as soon as the browser defines it. The JSON data as a parameter is a JS object and does not need to be parsed again.
But JSONP can only be used for HTTP requests with GET methods, which is more limited than CORS.
conclusion
These are some common cross-domain solutions, some of which are less commonly used as development approaches evolve, but understanding them can help us understand some of the underlying principles.