Cross-domain resource sharing (CORS)
Cross-domain resource sharing (CORS) is a mechanism based on HTTP Header. This mechanism allows the server to have permission to access resources on the loading server by allowing the server to indicate in addition to its own origin (domain, protocol, and port).
Cross-domain resource sharing Through the preflight request mechanism, check whether the server allows the real request to be sent. The browser sends a cross-domain resource hosted to the server Preflight request, In the preflight request, the header sent by the browser is marked with the HTTP method and the header used by the real request.
Preface
For security reasons, the browser will restrict cross-domain resource requests initiated in the script. For example, XMLHttpRequest and Fetch API follow the Same-origin policy, and non-same-original resource requests are not allowed by default. Web applications using these APIs can only load requested HTTP resources from the same domain of the application. Unless the response message contains the correct CORS response header
Overview
Cross-domain resource sharing A new set of HTTP header fields is added, allowing the server to declare which source sites have permission to access which resources through the browser. At the same time, for HTTP request methods that may have side effects on server data, the browser must first initiate a preflight request using the OPTIONS method. This will obtain whether the server allows cross-domain requests. Only after the server confirms that the permission is allowed will the actual HTTP request be initiated.
An error occurs when a CORS request fails, but for security, in JavaScript code, it is impossible to get the specific problem. We can only get the specific errors that appear by viewing the browser's console.
To enable CORS, we need to configure the CORS-related HTTP header field.
HTTP response header field
In CORS, the HTTP response header field mainly has the following:
- Access-Control-Allow-Origin
- Access-Control-Allow-Methods
- Access-Control-Allow-Headers
- Access-Control-Max-Age
- Access-Control-Expose-Headers
- Access-Control-Allow-Credentials
Access-Control-Allow-Origin
Access-Control-Allow-Origin Response header field, used to specify the out-of-domain URI that allows access to the resource.
For requests that do not require carrying credentials, the server can specify that the value of the field be changed to a wildcard character (*
), indicating that requests from all domains are allowed.
grammar:
Access-Control-Allow-Origin: <origin>
Access-Control-Allow-Origin: *
If the server specifies a specific domain name instead of *
, the value of the Vary field in the response header must contain Origin
. Used to tell the client that the server returns different content to different source sites.
Note
When responding to a request with credentials, the server must clarify the value of Access-Control-Allow-Origin, and cannot use the wildcard "*".
Example 1:
Allow access to all domains
Access-Control-Allow-Origin: *
Example 2:
Allow requests from https://pengzhanbo.cn
Access-Control-Allow-Origin: https://pengzhanbo.cn
Vary: Origin
Access-Control-Allow-Methods
Access-Control-Allow-Methods The response header field is used to preflight the response of the request. Specifies the HTTP method or method list that is allowed to be used by the actual request.
grammar:
Access-Control-Allow-Methods: <method>[, <method>]*
Example:
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers
Access-Control-Allow-Headers The response header field is used to preflight the response of the request. Specifies the header field allowed in the actual request.
grammar:
Access-Control-Allow-Headers: <header-name>[, header-name]*
Access-Control-Allow-Headers: *
The following specific headers are always allowed without having to declare them specifically:
- Accept
- Accept-Language
- Content-Language
- Content-Type, but only one of the MIME types
application/x-www-form-urlencoded
,multipart/form-data
,text/pain
.
Example 1:
Custom request header. In addition to the request headers listed in the CORS security manifest, custom request headers are supported.
Access-Control-Allow-Headers: X-Custom-Header
Example 2:
Multiple custom request headers.
Access-Control-Allow-Headers: X-Custom-Header, X-My-Header
Access-Control-Max-Age
Access-Control-Max-Age The response header field indicates how long the return result of the preflight request can be cached**.
The return result refers to the information provided by: Access-Control-Allow-Methods and Access-Control-Allow-Headers.
grammar:
Access-Control-Max-Age: <delta-seconds>
delta-seconds indicates the maximum time (seconds) that the return result can be cached. In Firefox, the upper limit is **24 hours (86400 seconds). In Chromium, the upper limit is 2 hours (7200 seconds), and Chromium also stipulates that the default value is 5 seconds. If the value is **-1**, it means that caching is disabled, and OPTIONS preflight requests are required before each request.
**Example: **
Cache preflight requests for 10 minutes:
Access-Control-Max-Age: 600
Access-Control-Expose-Headers
Access-Control-Expose-Headers Response header field, listing which headers can be exposed to the outside as part of the response.
During cross-origin access, the getResponseHeader()
method of the XMLHttpRequest object can only get some of the most basic response headers by default.
By default, there are only seven simple response headers that can be exposed to the outside:
- Cache-Control
- Content-Language
- Content-Length
- Content-Type
- Expires
- Last-Modified
- Pragma
If you want the client to access other header information, you can list them.
grammar:
Access-Control-Expose-Headers: <header-name>[, <header-name>]*
**Example: **
Expose a non-simple response header:
Access-Control-Expose-Headers: X-My-Header
Expose multiple non-simple response headers:
Access-Control-Expose-Headers: X-My-Header, X-Custom-Header
Access-Control-Allow-Credentials
Access-Control-Allow-Credentials Response header field is used when requesting to include Credentials, Tell the browser whether it is possible to expose the response to the request to the front-end JavaScript code.
When the requested Credentials mode (Request.credentials) is include
, the browser will be exposed to the front-end JavaScript code when the value of Access-Control-Allow-Credentials** is true
.
Credentials can be cookies
, authorization headers
, or TLS client certificates
.
grammar:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Credentials Need to be with XMLHttpRequest.withCredentials
Or use the credentials
option in the Request()
constructor of the Fetch API. Credentials must be configured on both the front and back ends for CORS requests with credentials to succeed.
**Example: **
Allow credentials
Access-Control-Allow-Credentials: true
Using XHR with credentials:
const xhr = new XMLHttpRequest()
xhr.open('GET', 'https://pengzhanbo.cn', true)
xhr.withCredentials = true
xhr.send(null)
Use Fetch with credentials:
fetch('https://pengzhanbo.cn', {
credentials: 'include',
})
HTTP request header field
In CORS, the header field that can be used to initiate cross-domain requests is as follows:
- Origin
- Access-Control-Request-Method
- Access-Control-Request-Headers
These header fields do not need to be set manually.
When developers use XMLHttpRequest to initiate cross-domain requests, they are already set up.
Origin
Origin The request header field indicates the source site for the preflight request or actual request.
grammar:
Origin: <origin>
The value of the origin parameter is the URI of the source site. It does not contain any path information, only represents the server name.
Access-Control-Request-Method
Access-Control-Request-Method The request header field is used for preflight requests. The function is to tell the server the HTTP method used in the actual situation.
grammar:
Access-Control-Request-Method: <method>
Access-Control-Request-Headers
Access-Control-Request-Headers The request header field is used for preflight requests. The function is to tell the server the header field carried by the actual request.
grammar:
Access-Control-Request-Headers: <header-name>[, <header-name>]*
Pre-flight request
A CORS preflight request is used to check that the server uses CORS, that is, cross-domain resource sharing.
Preflight Request Send an OPTIONS request through Send an OPTIONS request, and the request header contains the following fields:
- Access-Control-Request-Method
- Access-Control-Request-Headers
- Origin
The browser will automatically issue a preflight request when necessary.
So under normal circumstances, front-end developers do not need to send such requests themselves.
Preflight requests and credentials
The CORS preflight request cannot contain credentials. The response to the preflight request must specify Access-Control-Allow-Credentials: true to indicate that the credentials can be carried for the actual request.
Simple Request
In some cases, CORS preflight requests are not triggered, and such requests can be expressed as simple requests.
If the request meets all the following conditions, it can be considered a simple request:
- Using GET, HEAD POST request method
- In addition to the header fields (Connection, User-Agent, etc.) that are automatically set by the user agent, and other headers defined in the Fetch specification as disable header name, Fields that are allowed to be set artificially are CORS-safety collection of header fields defined by the Fetch specification
- No XMLHttpRequest object in the request has registered any listening events. The XMLHttpRequest object can be accessed using the XMLHttpRequest.upload property.
- The ReadableStream object is not used in the request.
Assigned identity requests and wildcards
In response to a request with credentials:
The server cannot set the value of Access-Control-Allow-Origin to the wildcard
*
, but should set it to a specific domain, such as: Access-Control-Allow-Origin: <https://pengzhanbo.cn. >The server cannot set the value of Access-Control-Allow-Headers to the wildcard
*
, but should set it to a list of header names, such as: Access-Control-Allow-Headers: X-Custom-Header, Content-TypeThe server cannot set the value of Access-Control-Allow-Methods to the wildcard
*
, but should set it to a list of specific request method names, such as: Access-Control-Allow-Methods: POST, GET
Scenarios that require CORS
- HTTP request initiated using XMLHttpRequest
- HTTP request initiated using Fetch API
- Web fonts, cross-domain font resources used by CSS through
@font-face
- WebGL map
- Use drawImage to draw the Images/video screen to canvas
- CSS graphics from images
Safety
In actual usage scenarios, use as little as possible wildcard *
to allow access to all domains, or to allow all custom header fields. This may be risky in web security.