Security Series: cross domain resource sharing CORS

Time:2021-11-27

brief introduction

What is cross domain resource sharing? We know that a domain is composed of scheme, domain and port. These three parts can uniquely mark a domain or the address requested by a server. Cross domain resource sharing means that the server allows other domains to access the resources of its own domain.

CORS is a mechanism based on HTTP header detection, which will be described in detail in this paper.

CORS example

For security reasons, generally, a request initiated by a domain can only obtain its own resources, because mutual calls within domain resources are considered safe.

However, with the development of modern browser technology and Ajax technology, there is a demand to request other domain resources from JavaScript. We call this demand cross domain request.

For example, the client from the domainhttp://www.flydean.comDirectional domainhttp://www.abc.com/data.jsonRequest data.

So how does the client know whether the server supports CORS?

A request called preflight is used here. This request only confirms to the server whether it supports cross domain requests to access resources. When the client gets a response, it will really request cross domain resources in the server.

Although the client sets the HTTP request header to make CORS requests, the server also needs to make some settings to ensure that it can respond to the client’s requests. Therefore, this article is suitable for both front-end developers and back-end developers.

CORS protocol

Yes, if any request wants to be standardized, a standard protocol must be formulated. The same is true for CORS. CORS protocol mainly defines the request header and response header in http. Let’s learn more about it separately.

HTTP request headers

The first is the HTTP request header. The request header is the data carried by the client when requesting resources. The CORS request header mainly consists of three parts.

The first part is origin, which indicates the request or preflight request source that initiates cross domain resource requests:

Origin: <origin>

Origin only contains server name information, not any path information.

Note that the value of origin may be null

The second part is access control request method, which is a preflight request that tells the server the HTTP resource request method that will be used next time:

Access-Control-Request-Method: <method>

The third part is access control request headers, which is also a preflight request, telling the server the header data to be carried in the next real HTTP request. The data in the header corresponds to the access control allow headers on the server side.

Access-Control-Request-Headers: <field-name>[, <field-name>]*

HTTP response headers

With the client request, the server response is also required. Let’s see what HTTP header data the server needs to set.

  1. Access-Control-Allow-Origin

Access control allow origin indicates the domain of CORS allowed by the server. You can specify a specific domain or use * to receive all domains.

Access-Control-Allow-Origin: <origin> | *

Note that * cannot be used if the request contains authentication information.

Let’s take an example:

Access-Control-Allow-Origin: http://www.flydean.com
Vary: Origin

The above example shows that the server allows receiving data fromhttp://www.flydean.comA specific domain is specified here instead of using *. Because the server can set an allowed domain list, only one of the domain addresses is returned here. Therefore, a change: origin header information needs to be added below, indicating that access control allow origin will be automatically sent and changed with the origin information in the client request header.

  1. Access-Control-Expose-Headers

Access control expose headers refers to the header information that the server allows the client or CORS resources to access at the same time. The format is as follows:

Access-Control-Expose-Headers: <header-name>[, <header-name>]*

For example:

Access-Control-Expose-Headers: Custom-Header1, Custom-Header2

The above example will expose two headers, custom-header1 and custom-header2, to the client, and the client can obtain the values of these two headers.

  1. Access-Control-Max-Age

Access control Max age indicates how long the request result of preflight request will be cached. Its format is as follows:

Access-Control-Max-Age: <delta-seconds>

Delta seconds is in seconds.

  1. Access-Control-Allow-Credentials

This field is used to indicate whether the server side accepts the client’s request with the credentials field. If it is used in preflight request, it indicates whether subsequent real requests support credentials. Its format is as follows:

Access-Control-Allow-Credentials: true
  1. Access-Control-Allow-Methods

This field indicates the methods allowed to access resources, which is mainly used in preflight request. The format is as follows:

Access-Control-Allow-Methods: <method>[, <method>]*
  1. Access-Control-Allow-Headers

It is used in preflight request to represent the header field that can really be used to make a request. Its format is as follows:

Access-Control-Allow-Headers: <header-name>[, <header-name>]*

With the basic concept of CORS protocol, we can start using CORS to build cross domain resource access.

Basic CORS

Let’s first look at a basic CORS request. For example, our website ishttp://www.flydean.com, on a page in the website, we want to gethttps://google.com/data/dataA, the JS code we can write is as follows:

const xhr = new XMLHttpRequest();
const url = 'https://google.com/data/dataA';

xhr.open('GET', url);
xhr.onreadystatechange = someHandler;
xhr.send();

This request is the most basic CORS request. Let’s see what data the request sent by the client contains:

GET /data/dataA HTTP/1.1
Host: google.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Connection: keep-alive
Origin: http://www.flydean.com

The request related to CORS is origin, which indicates that the source domain of the request ishttp://www.flydean.com

The possible return results are as follows:

HTTP/1.1 200 OK
Date: Mon, 01 May 2021 00:23:53 GMT
Server: Apache/2
Access-Control-Allow-Origin: *
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/xml

[…Data…]

In the above returned results, you should note that access control allow origin: *, which means that the server allows all origin requests.

Preflighted requests

The above example is the most basic request. The client directly requests resources from the server. Next, let’s look at an example of preflight requests. The request of preflight requests is divided into two parts. The first part is the request judgment, and the second part is the real request.

Note that the get request will not be sent preflit.

When will preflight requests be sent?

When the client sends options methods to the server, for security reasons, because the server may not be able to accept these options methods, the client needs to send one first
Preflight requests: wait for the server to respond, and then send the real request after the server confirms. Let’s give an example.

const xhr = new XMLHttpRequest();
xhr.open('POST', 'https://google.com/data/dataA');flydean
xhr.setRequestHeader('cust-head', 'www.flydean.com');
xhr.setRequestHeader('Content-Type', 'application/xml');
xhr.onreadystatechange = handler;
xhr.send('<site>www.flydean.com</site>');

In the above example, we sent a post request to the server. In this request, we added a custom header: cust head. Because this header is not the standard header in HTTP 1.1, you need to send a preflight requests first.

OPTIONS /data/dataA HTTP/1.1
Host: google.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Connection: keep-alive
Origin: http://www.flydean.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: cust-head, Content-Type

Access control request method and access control request headers are added to the request.

The server response obtained is as follows:

HTTP/1.1 204 No Content
Date: Mon, 01 May 2021 01:15:39 GMT
Server: Apache/2
Access-Control-Allow-Origin: http://www.flydean.com
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: cust-head, Content-Type
Access-Control-Max-Age: 86400
Vary: Accept-Encoding, Origin
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive

Access control allow origin, access control allow methods and access control allow headers are returned in the response.

After receiving the response from the server, the client finds that it is equipped with subsequent requests and can continue to send real requests:

POST /data/dataA HTTP/1.1
Host: google.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Connection: keep-alive
cust-head: www.flydean.com
Content-Type: text/xml; charset=UTF-8
Referer: http://www.flydean.com/index.html
Content-Length: 55
Origin: http://www.flydean.com
Pragma: no-cache
Cache-Control: no-cache

<site>www.flydean.com</site>

In the real request, we don’t need to send the access control request * header tag, we just need to send the real request data.

Finally, we get the response from the server side:

HTTP/1.1 200 OK
Date: Mon, 01 May 2021 01:15:40 GMT
Server: Apache/2
Access-Control-Allow-Origin: http://www.flydean.com
Vary: Accept-Encoding, Origin
Content-Encoding: gzip
Content-Length: 235
Keep-Alive: timeout=2, max=99
Connection: Keep-Alive
Content-Type: text/plain

[Some data]

Request with authentication

Sometimes, the resources we need to access need to carry authentication information, which is transmitted through HTTP cookies, but the browser will not authenticate by default. For authentication, a specific mark must be set:

const invocation = new XMLHttpRequest();
const url = 'https://google.com/data/dataA';

function corscall() {
  if (invocation) {
    invocation.open('GET', url, true);
    invocation.withCredentials = true;
    invocation.onreadystatechange = handler;
    invocation.send();
  }
}

In the above example, we set withcredentials flag to indicate that this is a request with authentication.

The corresponding requests are as follows:

GET data/dataA HTTP/1.1
Host: google.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Connection: keep-alive
Referer: http://www.flydean.com/index.html
Origin: http://www.flydean.com
Cookie: name=flydean

We brought a cookie in the request, and the corresponding response of the server is as follows:

HTTP/1.1 200 OK
Date: Mon, 01 May 2021 01:34:52 GMT
Server: Apache/2
Access-Control-Allow-Origin: http://www.flydean.com
Access-Control-Allow-Credentials: true
Cache-Control: no-cache
Pragma: no-cache
Set-Cookie: name=flydean; expires=Wed, 31-May-2021 01:34:53 GMT
Vary: Accept-Encoding, Origin
Content-Encoding: gzip
Content-Length: 106
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain

[text/plain payload]

The server returned access control allow credentials: true, indicating that the server received credentials authentication and returned the set cookie option to update the client’s cookies.

Note that if the server supports credentials, the returned values of access control allow origin, access control allow headers and access control allow methods cannot be *.

summary

This paper briefly introduces the CORS protocol in HTTP protocol. It should be noted that CORS is actually the interaction between HTTP request header and response header.

This article has been included inhttp://www.flydean.com/cors/

The most popular interpretation, the most profound dry goods, the most concise tutorial, and many tips you don’t know are waiting for you to find!

Welcome to my official account: “those things in procedure”, understand technology, know you better!