Nginx cross domain settings


I. cross domain overview

1.1 homology strategy

Homology policy is a security policy. Homology refers to the same protocol, domain name and port. In consideration of security, the browser only allows interface interaction under this domain name. Client scripts from different sources cannot read and write each other's resources without explicit authorization.

The homology strategy is mainly based on the following possible security risks:

  1. Users visit COM, log in and conduct online banking operation. At this time, cookie s and other resources are generated and stored in the browser;
  2. Users suddenly visit another website;
  3. In the page, the website gets the bank's cookie, such as user name, login token, etc., and then initiates a query to Com operation;
  4. If the browser does not restrict the cross domain at this time, and the bank does not respond safely, the user's information may be leaked.

1.2 cross domain introduction

CORS is a W3C standard, whose full name is cross origin resource sharing. That is, request the resources of another domain name from the web page of one domain name. In essence, for such requests, as long as the protocol, domain name and port are different, they are regarded as cross domain, that is, they are regarded as different sources.

Generally, for security reasons, Nginx enables the same origin policy, which limits how documents or scripts loaded from the same source interact with resources from another source. This is an important security mechanism for isolating potentially malicious files.

However, if there are multiple different sub domains within the same company, and mutual visits are required between sub domains, cross domain can be realized at this time. Cross domain can be realized through JSONP and CORS.

be careful:

  1. If the cross domain problem is caused by protocol and port, the "front end" cannot be solved;
  2. In cross domain implementation, it is only identified by "the header of the URL", and it will not be judged according to whether the IP address corresponding to the domain name is the same. "URL header" can be understood as "protocol, domain name and port must match";
  3. The cross domain request does not mean that the request cannot be sent out. The request can be sent normally. The server can receive the request and return the result normally, but the result is intercepted by the browser.

Tip: this experiment is based on the cross domain implementation of CORS of Nginx. For more JSONP and other references: .

1.3 cross domain processing flow

  1. First, check whether there is an origin field in the http header;
  2. If not, or not allowed, it will be handled directly as an ordinary request and end;
  3. If yes and allowed, check whether it is preflight(method=OPTIONS);
  4. If it is preflight, allow headers and allow methods will be returned, and the content is empty;
  5. If it is not preflight, allow origin, allow credentials, etc. will be returned, and normal content will be returned.
  1 location /pub/(.+) {
  2     if ($http_origin ~ <Allowed fields (regular matches)>) {
  3         add_header 'Access-Control-Allow-Origin' "$http_origin";
  4         add_header 'Access-Control-Allow-Credentials' "true";
  5         if ($request_method = "OPTIONS") {
  6             add_header 'Access-Control-Max-Age' 86400;
  7             add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, DELETE';
  8             add_header 'Access-Control-Allow-Headers' 'reqid, nid, host, x-real-ip, x-forwarded-ip, event-type, event-id, accept, content-type';
  9             add_header 'Content-Length' 0;
 10             add_header 'Content-Type' 'text/plain, charset=utf-8';
 11             return 204;
 12         }
 13     }
 14     # Normal nginx configuration
 15     ......
 16 }

II. Introduction to CORS

CORS implementation

CORS requires both browser and backend support. After the backend is configured with CORS to realize cross domain, the browser will automatically communicate with CORS to realize cross domain.

2.2 request type

In the scenario of using CORS, the common requests of the client (front end) can be classified into the following two types:

  • Simple request: as long as the following two conditions are met at the same time, it is a simple request

Methods: GET, HEAD, POST.

Content: the value of content type is limited to one of the following three:

    • text/plain;
    • multipart/form-data;
    • Any XMLHttpRequestUpload object in the application/x-www-form-urlencoded request does not register any event listeners.
  • Complex request

Methods: DELETE, PUT.

A request that does not meet the above conditions must be a complex request. For CORS requests with complex requests, an HTTP query request will be added before formal communication, which is called "pre check" request. The request is of the option method. It is used to know whether the server allows cross domain requests.

III. Nginx cross domain configuration

3.1 configuration syntax

Syntax: add_header name value [always];


Configurable segment: http, server, location, if in location

Definition of configuration item:

  • Access control allow Origin: configured as * indicates that the server can accept all request sources, that is, accept all cross domain requests, or specify a certain URL.
  • Access control allow headers: configure access control allow headers to allow the specified request header when requesting the address, such as content type, Authorization, Use commas (,) to put them in double quotation marks ("), which can be added according to the actual request type to prevent the following errors: request header field content type is not allowed by access control allow headers in preflight response. This error indicates that the value of the current request content type is not supported. In fact, it is caused by the type request of" application/json ".
  • Access control allow methods: configure access control allow methods to allow the address to be requested using the specified method. Common methods are: GET, POST, OPTIONS, PUT, PATCH, DELETE, HEAD. Content type is not allowed by access control allow headers in preflight response
  • Access control Max age: configure access control Max age, which means that when you don't need to request the address within 86400 seconds, you don't need to make a pre check request, that is, cross domain cache.
  • Access control allow credentials' true ': optional field. True indicates that cookies are allowed to be sent. Meanwhile, XMLHttpRequest must be set when sending Withcredentials is valid only when it is true. If the server does not allow the browser to send the request, delete this field.
  • return 204: add a return of 204 to OPTIONS. In order to handle the error that Nginx still refuses access when sending a POST request, the method OPTIONS needs to be used when sending a "pre check request", so the server needs to allow this method.
  1. For simple requests, such as GET, you only need to add access control allow origin after the HTTP Response.
  2. For non simple requests, such as POST, PUT, DELETE, etc., the browser will respond twice. The first preflight (method: OPTIONS) mainly verifies whether the source is legal and returns the allowed headers. The second time is the real HTTP response. Therefore, the server must process the OPTIONS reply.

Note: add above_ Finally, always can be added to the header, which means that add will be added no matter what the returned status code is_ The header takes effect. Sometimes the server may return 4XX status code. At this time, if always is missing, add will be caused_ The header fails, causing the browser to report a cross domain error.

2.2 configuration example

Scheme 1 *: wildcards, all allowed, with potential safety hazards (not recommended). Once this method is enabled, it means that any domain name can be requested directly across domains:

  1     server {
  2         ...
  3         location / {
  4             # Allow all headers, all domains, all methods
  5             add_header 'Access-Control-Allow-Origin' '*';
  6             add_header 'Access-Control-Allow-Headers' '*';
  7             add_header 'Access-Control-Allow-Methods' '*';
  8             # OPTIONS returns 204 directly
  9             if ($request_method = 'OPTIONS') {
 10                 return 204;
 11             }
 12         }
 13         ...
 14     }

Scheme 2: multi domain name configuration (recommended)

Configure multiple domain names. Only those configured in the map are allowed to cross domains:

  1  map $http_origin $corsHost {
  2         default 0;
  3         "~";
  4         "~";
  5         "~";
  6     }
  7     server {
  8         ...
  9         location / {
 10             # Allow all headers all $corsHost domain all methods
 11             add_header 'Access-Control-Allow-Origin' $corsHost;
 12             add_header 'Access-Control-Allow-Headers' '*';
 13             add_header 'Access-Control-Allow-Methods' '*';
 14             # OPTIONS returns 204 directly
 15             if ($request_method = 'OPTIONS') {
 16                 return 204;
 17             }
 18         }
 19         ...
 20     }

4, More examples

4.1 distinguishing requests across domains

  1 server
  2 {
  3     listen 80;
  4     server_name;
  5     root root   /usr/share/nginx/multireq01;
  6     access_log  /var/log/nginx/multireq01.access.log  main;
  7     error_log   /var/log/nginx/multireq01.error.log  warn;
  8     location /
  9     {
 10         if ($request_method = 'OPTIONS') {
 11             add_header 'Access-Control-Allow-Origin' '*';
 12             add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
 13             add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
 14             add_header 'Access-Control-Max-Age' 1728000;
 15             add_header 'Content-Type' 'text/plain charset=UTF-8';
 16             add_header 'Content-Length' 0;
 17             return 204;
 18         }
 19         if ($request_method = 'POST') {
 20             add_header 'Access-Control-Allow-Origin' '*';
 21             add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
 22             add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
 23         }
 24         if ($request_method = 'GET') {
 25             add_header 'Access-Control-Allow-Origin' '*';
 26             add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
 27             add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
 28         }
 29     }
 30 }

4.2 differentiated request cross domain II

  1 server
  2 {
  3     listen 80;
  4     server_name;
  5     root root   /usr/share/nginx/multireq02;
  6     access_log  /var/log/nginx/multireq02.access.log  main;
  7     error_log   /var/log/nginx/multireq02.error.log  warn;
  8     location /
  9     {
 10         if ($request_method = 'OPTIONS') {
 11             add_header 'Access-Control-Allow-Origin' '';
 12             add_header 'Access-Control-Allow-Credentials' 'true';
 13             add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, PATCH, OPTIONS';
 14             add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization,token';
 15             return 204;
 16         }
 17         if ($request_method = 'POST') {
 18             add_header 'Access-Control-Allow-Origin' '';
 19             add_header 'Access-Control-Allow-Credentials' 'true';
 20             add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, PATCH, OPTIONS';
 21             add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization,token';
 22         }
 23         if ($request_method = 'GET') {
 24             add_header 'Access-Control-Allow-Origin' '';
 25             add_header 'Access-Control-Allow-Credentials' 'true';
 26             add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, PATCH, OPTIONS';
 27             add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization,token';
 28         }
 29     }
 30 }

Posted by coolfool on Thu, 05 May 2022 06:31:23 +0300