1 Preface:
First of all, thank you for the reference article author, and your experience concludes that we have too many resources for these novices.
This article is devoted to solving the problem of the cors of Ajax, and I comb it logically: firstly, the author summarizes the origin of the cors problem-homologous strategy, and secondly, introduces the cross-domain mode and cors comparison of JSONP which can only support get request; This paper expounds the XHR solution of Cors and the XDR solution in IE, and provides the tool function to create the cross-browser HTTP request object.
2 origin of cross-domain problem-homologous policy
In client-side programming languages, such as JavaScript and ActionScript, the same-origin policy is an important security concept that is designed to keep users ' information safe from malicious websites stealing data.
Imagine a situation where a site is a bank, users log in, and then visit other websites. What happens if other websites can read the Cookie of the A site?
Obviously, if a Cookie contains privacy (such as a total deposit), the information is leaked. What's more scary is that cookies are often used to save a user's login status, and if the user does not log out, the other sites can impersonate the user and do whatever they like. Because the browser also stipulates that the submission form is not subject to the same-origin policy restrictions. Thus, the "homologous policy" is necessary, otherwise the Cookie can be shared, the Internet is not safe to speak of.
So what is called the same domain (homologous), what is the different domain (not the same origin)? When two domains have the same protocol (such as HTTP), the same ports (such as 80), the same host (such as www.example.org), then we can think of them as the same domain. such as Http://www.example.org/index .... (Default port number 80 can be omitted) and http://www.example.org/sub/in ... Is the same domain, and any two of http://www.example.org, https://www.example.org, http://www.example.org:8080, http://sub.example.org will form a cross-domain.
Note: Only the protocol, domain name, port number is exactly the same domain, in other cases, even if the corresponding IP and domain names are also different domains, such as:
(This picture forgot where it was attracted, thanks to the author)
At present, if the non-homologous, a total of three acts are limited.
(1) Cookies, localstorage and indexdb cannot be read.
(2) DOM is not available.
(3) AJAX requests cannot be sent.
As front-end developers, a lot of the time we have to do is to break this limit.
Supplement: The same-origin strategy should also handle some special cases, such as restricting access to scripts under the file protocol. The local HTML file in the browser is opened through the file protocol, if the script can be accessed through the file protocol to any other files on the hard disk, there will be a security risk, the current IE8 still have such a hidden danger.
3 cross-domain mode jsonp[reference 1]
JSONP is a shorthand for JSON with padding, and is a common method of applying JSON for server-to-client cross-origin communication. The biggest feature is simple to use, old browsers all support, server transformation is very small.
The basic idea is that Web pages request JSON data from the server by adding a <script> element that is not subject to the same-origin policy; After the server receives the request, it returns the data in a callback function with the specified name.
Jsop consists of two parts: the callback function and the data, which is the function that should be called when the response arrives, usually by the query string, and the data is the JSON data in the callback function, which is exactly a JSON object that can be accessed directly.
Instance:
Functions that access the cross-domain src and populate the data into the script tag
function Addscripttag (SRC) {
var script = document.createelement (' script ');
Script.setattribute ("type", "Text/javascript");
SCRIPT.SRC = src;
Document.body.appendChild (script);
}
Web page Dynamic Insert <script> element, which makes a request to the cross-origin URL src, which contains a callback function in SRC
Window.onload = function () {
Addscripttag (' Http://example.com/ip?callback=foo ');
}
The parameters of the callback function are the returned data by default
function foo (data) {
Console.log (' Your public IP address is: ' + data.ip);
};
/The above code makes a request to the server example.com by dynamically adding <script> elements. Note that the query string for the request has a callback parameter that specifies the name of the callback function, which is required for JSONP. /
Disadvantages of Jsonp
You can only implement get, no post, code that is loaded from another domain may not be secure, it is difficult to determine if the JSONP request failed (XHR has an error event), and a common practice is to use the timer to specify the allowable time for the response and the time to think that the response failed. Cors uses the same purpose as JSONP, but is more powerful than JSONP, and it supports all types of HTTP requests. The advantage of JSONP is that it supports older browsers and can request data from sites that do not support cors.
4 Ajax Implementation Cross-domain [reference 2]
Complex HTTP requests are described in reference [2], and this article contains only simple get and post requests.
CORS, Cross-origin Resource Sharing (https://www.w3.org/TR/cors/), is a cross-domain resource sharing that defines how the browser interacts with the server when resources must be accessed across domains. The basic idea is to use a custom HTTP header to communicate with the browser and server to determine the success and failure of the response. Therefore, understanding the XHR cross-domain must understand the HTTP header.
4.1 HTTP Header
The HTTP header is divided into the request header and the response header, and the following request headers are sent when the XHR request is sent:
? Accept: The type of content that the browser can handle.
? Accept-charset: The character set that the browser can display.
? Accept-encoding: The compression encoding that the browser can handle.
? Accept-language: The language currently set by the browser.
? Connection: The type of connection between the browser and the server.
? Cookie: Any cookie that is set on the current page.
? Host: The domain of the page where the request was made.
? Referer: The URI of the page that issued the request. Note that the HTTP specification incorrectly spelled this header field, and to ensure consistency with the specification, it can only be will wrong. (the correct spelling of this English word should be referrer.) )
? User-agent: The user agent string for the browser.
Content-type: Limited to three values application/x-www-form-urlencoded, Multipart/form-data, Text/plain
Use the setRequestHeader () method to set the custom request header information. This method takes two parameters: the name of the header field and the value of the header field. To successfully send the request header information, the setRequestHeader () must be called before the Open () method is called and before the Send () method is called.
Request.open ("GET", "Https://sf-static.b0.upaiyun.com/v-57fcb48b/user/script/index.min.js", true);
Xhr.setrequestheader ("MyHeader", "myvalue");
Request.send (NULL);
After the server receives this customized header information, it can perform subsequent operations accordingly.
Call the getResponseHeader () method of the XHR object and pass in the header field name to get the corresponding response header information. The call to the getAllResponseHeaders () method allows you to get a long string containing all the header information, and this formatted output allows us to check the names of all header fields in the response.
Test Example:
Create Request Object
var request = Createrequest ();
if (request = = null) {
Alert ("Unable to create request");
Return
}
Request.onreadystatechange = Showschedule;
Add event handler using the DOM0-level method, because not all browsers support DOM2; No event object, directly using the Request object
Request.open ("GET", Selectedtab + ". html", true);//return HTML fragment
Request.send (NULL);
}
function Showschedule () {
if (request.readystate = = 4) {
if ((Request.status >= && request.status <=) | | request.status = 304) {
Return response Header
document.getElementById ("Content"). InnerHTML = Request.getallresponseheaders ();
}else
{
document.getElementById ("Content"). InnerHTML =request.status;
}
}
}
The output shows the full response header:
Last-modified:tue, Oct 09:44:48 GMT content-type:application/x-javascript cache-control:max-age=2592000 expire S:thu, 09:45:10 GMT
4.2 CORS involves the head
WebKit in IE10 and above, Firefox 3.5+, Safari 4+, Chrome, IOS Safari, and Android platforms have native support for CORS through XMLHttpRequest objects. Cors can be achieved by using absolute positioning in the URL of the open () method. It is generally recommended to use relative URLs in the same domain, using absolute URLs when crossing domains. The entire cors communication process is done automatically by the browser and does not require user involvement. For developers, Cors Communication is no different from the same-Origin Ajax communication, and the code is exactly the same. Once the browser discovers that the AJAX request crosses the source, it automatically adds some additional header information, sometimes with an additional request, but the user does not feel it. Therefore, the key to achieving cors communication is the server. As long as the server implements the Cors interface, it can communicate across the source.
For simple requests (get and post), the browser makes a cors request directly. Specifically, in the header information, add an Origin field to illustrate: which source (protocol + domain + port) The request came from. Based on this value, the server decides whether to agree to this request.
If origin specifies a source that is not within the scope of the license, the server returns a normal HTTP response. The browser found that the header information for this response did not contain the Access-control-allow-origin field (see below), and knew that an error occurred, thus throwing a bug that was captured by the XMLHttpRequest OnError callback function. Note that this error cannot be identified by the status code because the status code of the HTTP response is likely to be 200.
If the domain name specified by origin is within the scope of the license, the response returned by the server will have a few more header information fields, as follows:
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
Among the header information above, there are three fields related to cors requests, all starting with access-control-. Detailed explanations are as follows:
(1) Access-control-allow-origin
This field is required. Its value is either the value of the Origin field at the time of the request, or one that represents the request to accept any domain name.
(2) Access-control-allow-credentials
This field is optional. Its value is a Boolean value that indicates whether the cookie is allowed to be sent. By default, cookies are not included in Cors requests. Set to true, which means that the server explicitly permits the cookie to be included in the request and sent to the server. This value can only be set to TRUE if the server does not send a cookie to the browser, delete the field.
(3) Access-control-expose-headers
This field is optional. Cors request, the XMLHttpRequest object's getResponseHeader () method can only get 6 basic fields: Cache-control, Content-language, Content-type, Expires, Last-modified, Pragma. If you want to get the other fields, you must specify them in the Access-control-expose-headers. The above example specifies that getResponseHeader (' FooBar ') can return the value of the FooBar field.
4.3 Test examples
Change the Open () method in the above example to the following, and the URL points to a JavaScript file in the other domain, and the test results indicate that the file can be loaded successfully.
The test file is on local host localhost
Request.open ("GET", "https://sf-static.b0.upaiyun.com/v-57fcb48b/user/script/index.min.js"/Selectedtab + "). HTML "/, True);
Use Firefox's firebug to observe the response process for the above request, corresponding to the request header: Origin is http://localhost
Response header: Access-control-allow-origin: can be accessed on behalf of any source.
XHR objects that are used across domains can access the status and StatusText properties and support synchronous requests, although this is not much use. The restriction is that you cannot set a custom header with setRequestHeader (), that you cannot send and receive cookies, and that calling the getAllResponseHeaders () method always returns an empty string.
5 Special IE:XDR Objects for cross-domain
Support for the Xhr2,ie browser is IE10 or more. However, ie early in IE8 launched the Xdomainrequest object for cross-domain operation, has been used until IE10 was replaced. Therefore, Xdomainrequest (XDR) should be used in IE8,IE9. XDR has the following characteristics:
1) The cookie is not sent with the request and is not returned with the response. (As with cross-domain XHR)
2) only the Content-type field in the request header information can be set.
3) cannot access the response header information. (As with cross-domain XHR)
4) only GET and POST requests are supported.
XDR objects are used in a very similar way to XHR objects, creating an instance of Xdomainrequest, calling the open () method, and then calling the Send () method. However, unlike the Open () method of the XHR object, the Open () method of the XDR object only receives two parameters: the type of the request and the URL.
All XDR requests are executed asynchronously and cannot be used to create synchronization requests (unlike XHR). After the request is returned, the Load event (and XHR) is triggered, and the error event is triggered if the failure (including missing access-control-allow-origin headers in the response) occurs. The data for the response is also saved in the ResponseText property.
var xdr = new Xdomainrequest ();
Xdr.onload = function () {
alert (Xdr.responsetext);
};
Xdr.open ("Get", "http://www.somewhere-else.com/page/");
Xdr.send (NULL);
Calling the Abort () method before the request returns can terminate the request:
Xdr.abort (); Terminate request
Like XHR, XDR objects also support the Timeout property and the OnTimeOut event handler.
To support POST requests, the XDR object provides the ContentType property, which is used to represent the format in which the data is sent. This property can affect header information, which is used before the open (), send (). This property is the only way to affect header information through an XDR object.
6 cross-browser cross-domain solutions
Even though browsers do not have the same level of support for CORS, all browsers support simple (non-preflight and non-credential) requests, so it is necessary to implement a cross-browser scenario. The simplest way to detect whether XHR supports CORS is to check for the presence of withcredentials properties. By combining the detection of Xdomainrequest objects, it is possible to reconcile all browsers.
function Createcorsrequest (method, URL) {
var xhr = new XMLHttpRequest ();
if ("Withcredentials" in XHR) {
Xhr.open (method, URL, true);
} else if (typeof xdomainrequest! = "undefined") {
VXHR = new Xdomainrequest ();
Xhr.open (method, URL);
} else {
XHR = null;
}
return XHR;
}
The XMLHttpRequest objects in Firefox, Safari, and Chrome are similar to the Xdomainrequest objects in IE, and provide the following common properties/methods:
? Abort (): Used to stop a request that is in progress.
? OnError: Used to replace onreadystatechange detection error.
? OnLoad: Used to replace onreadystatechange detection success.
? ResponseText: Used to get response content.
? Send (): Used to send the request.
The above members are included in the object returned by the Createcorsrequest () function and are available in all browsers.
var request = Createcorsrequest ("Get", "http://www.somewhere-else.com/page/");
if (request) {
Request.onload = function () {
Handling of Request.responsetext
};
Request.send ();
}
Reprinted article, original address: http://www.th7.cn/web/js/201610/191329.shtml
Ajax Learning notes 2:XHR for cross-domain resource sharing (CORS) and comparison with JSONP