CORS you should know

Time:2019-12-2

What you should know about CORS
By Nicolas Bailly
Translator: Boxuan

CORS you should know

If you’re like me, the first timeCORS(cross domain resource sharing), you want the server to receive those you splicedAjaxRequest and process them. So you go to stackoverflow.com and copy a piece of code to set up some HTTP headers so that the request can work normally.

But there may be other things you should know.

What is CORS, not what

The reason novices are often confused is because they are not clearCORSWhat can be done. First,CORSIt’s not a security measure, it’s actually the opposite:CORSIt’s a way to bypass the same origin strategy (SOP). The same origin policy is a security measure that prevents you from issuing to other domainsAjaxRequest.

The same origin policy declares a web site on one domain and cannot issue an XMLHttpRequest (XHR) request to another domain. This prevents malicious websites from making requests to known websites, such as Facebook or Google, to change the user’s login status so that they can impersonate other users. This policy is implemented by browsers (all browsers implement the same origin policy, although there are subtle differences in implementation details), which means that this policy is not applicable to requests from servers or any other HTTP clients (such as curl, postman). In addition, the server also has no full control over it: the server will process each request and assume that they are from a trusted domain, and whether the request will be blocked depends entirely on the browser.

Homologous strategyIn no way does it prevent an attacker from making requests to your server (because it is clear that the attacker will not use the browser). It’s just to prevent legitimate users from making requests to your website without their knowledge when browsing the website with a well-known browser.

CORSIt’s a way to bypass the same origin policy. In some cases, you want some special sites to make requests to your server, even if it’s normally blocked. Typically, it allows your front-end application to make requests to your API.

How CORS works

AndHTTPThe same.CORSIt’s basically a conversation between the browser and the server. Suppose your front-end domain name isdomain-a.com, the domain name of the backend API isdomain-b.com, the conversation will be like this:

  • Browser:“Hey domain-b.comdomain-a.comThe script on will launch to you onceAjaxPlease, but I should stop it, unless you tell me it’s OK. “
  • The serverI don’t know, but I can tell you,https://domain-a.comOnly get, post, options and delete requests are allowed to be sent and need to be verified every 10 minutes. “

BrowserThink about it: “Yeah, this is the right domain name. I should send him a request.”

  • Browser:“Hey domain-b.comI want to send you a post request at this terminal. “
  • The server“No problem, this is yours200

Or, if the user is in a different domain, the conversation is shorter:

  • Browser:“Hey domain-b.commalicious-domain.comThis script on (malicious site) will launch to you onceAjaxPlease, but I should stop it, unless you tell me it’s OK. “
  • The serverI don’t know, but I can tell you,https://domain-a.comOnly get, post, options and delete requests are allowed to be sent and need to be verified every 10 minutes. “

BrowserThink about it: “Oh, this is not the right domain name, we’d better not send the request”, and then print the error in the console.

Note: second, when you use the developer tool to view, you cannot see the response headers, but you can see the prompt in the following figure:

CORS you should know

Node CORS test address

What it looks like in a browser

In the above scenario, the first question raised by the browser is called the pre check request, and the corresponding HTTP predicate isOPTIONS。 In case of such a pre check request, the server should always return a 200 response with no body, but it will containAccess-Control-Allow-Origin, and some other response headers. In our example, the response header is as follows:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://domain-a.com
Access-Control-Allow-Methods: GET, POST, OPTIONS, DELETE
Access-Control-Max-Age: 3600

It tells the browser that it can only respond to requests fromdomain-a.comIt can process get, post, options or delete requests (put requests will be blocked), and it can cache this information for 3600 seconds, so it does not need to initiate a newOPTIONSRequest.

CORS you should know

Of course, it won’t work if we use other domains. Browser will sendOPTIONSRequest, then throw an exception in the console, and never send itPOSTRequest.

CORS you should know

It’s direct, isn’t it?

But there are some pitfalls

On the knotty problems of CORS

All requests contain CORS headers(headers

You may think that if your server respondsOPTIONS200 on request, and then you remove the correct response headers. And then you’ll see that the browser sent it firstOPTIONSRequest, and then sent other requests, other requests hung up… This is because each request (get, post, or other request) should contain the same response header: “access control allow headers”.

Not all requests trigger a pre check request

Some requests do not trigger a pre check request, such as a get request, orContent-TypeSet toapplication/x-www-form-urlencodedPost request for. These are the “simple requests” that browsers always allow (even if CORS doesn’t support them, you can still use hyperlinks(aTag) or use post to request forms to other sites, where you can find the full list. In the case of a post request, the result is a bit counterintuitive: the browser will make a post request (so your server may keep some data), and then ignore the response.

In traditional web applications, you can use theapplication/jsonAct ascontent-type, so there will be pre check requests, but remember that your server may still receive post requests from other domains, so don’t blindly accept them.

The allowed domain name must contain a protocol

You can’t justmydomain.comAs a domain name, it also needs to contain protocols (for example:https://mydomain.com) Interestingly, you can’t receive it at the same timehttpandhttpsBecause

You can only allow one domain

You can use theAccess-Control-Allow-Origin: *To allow each domain access, or only one domain access. This means that if you need more than one domain to access yourAPIWhen, you need to deal with it yourself.

The easiest way to deal with this problem is to maintain the list of domains allowed to access on the server. If the domain is in the list, the content of the response header will be changed dynamically. Here is an example of PHP:

$allowedDomains = [
    "http://www.mydomain.com",
    "https://www.mydomain.com",
    "http://www.myotherdomain.com",
    "http://www.myotherdomain.com",
];

$originDomain = $_SERVER['HTTP_ORIGIN'];

if (in_array($originDomain, $allowedDomains)) {
    header("Access-Control-Allow-Origin: $originDomain");
};

Or the example of node.js (adapted from the stackoverflow answer)

app.use(function(req, res, next) {
  const allowedOrigins = [
    "http://www.mydomain.com",
    "https://www.mydomain.com",
    "http://www.myotherdomain.com",
    "http://www.myotherdomain.com",
  ];
  const origin = req.headers.origin;
  if(allowedOrigins.indexOf(origin) > -1){
    res.setHeader('Access-Control-Allow-Origin', origin);
  }
  return next();
});
The same origin policy is applicable to the file systems of chrome and safari, not Firefox

If you make a request to a local file, Firefox assumes that it is always on the same domain and allows the request. Be based onWebkit‘s browser, such as chrome or Safari, treats this as a security risk and blocksAjaxQuery. The only way to solve this problem is to use Firefox, or install will sendAccess-Control-Allow-Origin: *Web server for the response header.
As @ Brian Jenkins 94 points out in the comments, you can also use the--disable-web-securityParameter to start chrome.

IOS wkwebview requires CORS

If you are developing and usingwebviewAndroid (using Cordova or ionic) mobile app will not cause you any trouble, but new on IOSWKWebviewCORS will be required. This means that you almost always have toAccess-Control-Allow-OriginHeader set to*But it’s not ideal.
Another option is not to issue in your applicationAjaxRequest and usecordovaPlug in cost machinehttpRequest, which will easily bypass the same origin policy.

Thank you for reading!
If you want to learn more about CORS, visit MDN:
https://developer.mozilla.org…

The author of this article has been contacted and authorized to translate. Please keep the original link for reprint