Introduction to the

Cross-source resource sharing (CORS) (or cross-domain resource sharing as it is collocially translated) is a mechanism that uses additional HTTP headers to tell browsers to allow Web applications running on one source to access selected resources located on a different source. When a Web application makes an HTTP request that is different from its own source (domain, protocol, or port), it makes a cross-source HTTP request.

For security, browsers restrict cross-source HTTP requests that can be made within a script. For example, the XMLHttpRequest and Fetch apis follow the same origin policy. This means that Web applications using these apis can only request HTTP resources from the same domain that loaded the application, unless the response message contains the correct CORS response header.

Notice that since the browser judges the response header, the server has actually received the request. Only the return value is blocked by the browser

implementation

Cross-source resource sharing standards have added a new set of HTTP header fields that allow servers to declare which source sites have access to which resources through the browser. In addition, the specification requires that HTTP request methods (especially HTTP requests other than GET, or POST requests paired with certain MIME types) that may have adverse effects on server data, The browser must first issue a preflight request using the OPTIONS method to know if the server will allow the cross-source request. The actual HTTP request is made only after the server confirms that it is allowed. In the return of the precheck request, the server side can also inform the client whether it needs to carry identity credentials (including Cookies and HTTP authentication related data).

CORS request failures generate errors, but for security reasons, there is no way to know exactly what went wrong at the JavaScript code level. You can only look at your browser’s console to see exactly what went wrong.

The trigger condition

A simple request does not trigger CORS. A simple request is a simple request if the following three conditions are met

Some requests do not trigger CORS precheck requests. This article refers to such a request as a “simple request,” noting that the term is not part of the Fetch (where CORS is defined) specification. A request is considered a “simple request” if all of the following conditions are met:

  1. Use one of the following methods:

GET HEAD POST 2. Headers that are automatically set by the User Agent (e.g., Connection, user-agent) and other headers that are defined in the Fetch specification as disabled header names, Fields that are allowed to be set artificially are the set of cORs-safe header fields defined by the Fetch specification. The set is: Accept accept-language content-language content-type DPR Downlink Save-Data viewport-width Width 3. Content-type values are limited to one of the following: Text /plain Multipart /form-data application/ X-www-form-urlencoded

The solution

  • The server using access-Control-request-headers can be used to handle custom Headers in case 2
  • Access-control-allow-methods can be used to handle case one
  • Access-control-allow-origin is used to process the domain name whitelist
  • Access-control-max-age specifies the cache time to initiate precheck requests (note that the browser itself maintains a maximum value, which is invalid if exceeded)
  • Access-control-expose-headers is used to ask the browser to carry some Headers (otherwise you’ll only get the most basic ones)

cookie

In general, cross-domain requests do not carry cookies. If you need to carry cookies, special Settings need to be made when the request is made, first at request time

var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://example.com/', true); 
xhr.withCredentials = true; 
xhr.send(null);

// Fetch
fetch(url, {
  credentials: 'include'  
})


Copy the code
  1. Setting is required at request time
  2. Access-control-allow-credentials: true in response headers (if false, the browser will not return the content to the sender)
  3. The server must not set access-Control-allow-origin to *. Otherwise, the request will fail

In addition, the response header also carries the set-cookie field, which attempts to modify the Cookie. If the operation fails, an exception will be thrown

CORS middleware processing

  1. For non-options requests, access-control-allow-origin, access-Control-allow-credentials, Access-control-expose-headers;
  2. Access-control-allow-origin, access-Control-allow-credentials, access-control-max-age, access-control-credentials, access-control-credentials, access-control-credentials, access-control-max-age, access-Control-credentials, access-control-credentials, access-control-credentials Access-control-allow-methods access-Control-allow-headers Headers

The verification results

Cross-domain GET requests

Fetch ('http://127.0.0.1:4321').then(function (response) {if (response.ok) {response.json(). Then (function (data) { console.log(data); }); } else {console.log(' request failed, status code ', response.status); }}, function(err) {console.log(' error: ', err); });Copy the code

Simple cross-domain POST request

Fetch (' http://127.0.0.1:4321/post '{method: "POST", headers: {' the content-type: 'application/x-www-form-urlencoded' }, body: 'firstName=Nikhil&favColor=blue&password=easytoguess' }).then(function(res) { if (res.ok) { console.log('Perfect! Your settings are saved.'); } else if (res.status == 401) { console.log('Oops! You are not authorized.'); } }, function(e) { console.log('Error submitting form! '); });Copy the code

failure

Cross-domain Non-simple POST Request (JSON)

Fetch (' http://127.0.0.1:4321/post '{method: "post", headers: {' Accept' : 'application/json, text/plain, */*', 'Content-Type': 'application/json' }, body: JSON.stringify({a: 7, str: 'Some string: &=&'}) }).then(res=>res.json()) .then(res => console.log(res));Copy the code

Result: The server can’t even receive the request

The resources

  • CORS MDN document
  • CORS principle and @KOA/CORS source code analysis