Why do cross-domain problems occur? Because of the same origin policy restrictions of the browser. The same origin policy restricts how documents or scripts loaded from the same source can interact with resources from another source. This is an important security mechanism for isolating potentially malicious files.

A same-origin Policy

1.1 Definition of homology

The Same Origin policy (SOP) means that the protocol, domain name, and port are the Same. Even if two domain names point to the Same IP address, they are not of the Same origin. The same origin policy restricts how documents or scripts loaded from the same source can interact with resources from another source. This is an important security mechanism for isolating potentially malicious files.

1.2 Source inheritance

Scripts executed on a page with an about:blank or javascript: URL inherit the source of the document that opens that URL, because these types of URLs do not contain information about the source server.

For example, about:blank is usually the URL of a new blank pop-up Window that the parent script writes to (for example, window.open ()). If this pop-up window also contains JavaScript, the script inherits the corresponding source from the script that created it.

1.3 Source changes

A script can set the value of document.domain to its current field or to the parent of its current field.

The port number is checked separately by the browser. Any assignment to document.domain, including document.domain = document.domain, will result in the port number being overwritten to NULL. Therefore company.com:8080 cannot communicate with company.com only by setting document.domain = “company.com”. Assignment must be made on both of them to ensure that the port numbers are null. Document.domain =document.domain, the Cookie is shared between two different ports. But I don’t know how to recover.

1.4 Cross-source Network Access

The same origin policy controls interactions between different sources, such as when using XMLHttpRequest or < IMG > tags. These interactions generally fall into three categories:

  • Cross-domain _The write operation(Cross – origin writes)It’s generally allowed. Examples include links, redirects, and form submission. A few HTTP requests need to be addedpreflight(Precheck request).
  • Cross-origin embedding is generally allowed.
  • Cross-domain _A read operation(Cross – origin reads)It’s generally not allowed, _ but it is often possible to do clever read access with embedded resources. For example, you can read the height and width of an embedded image, call the methods of an embedded script, oravailability of an embedded resource.

1.5 Scope of Limitation

  1. Cookie, LocalStorage, and IndexDB cannot be read.
  2. DOM is not available.
  3. AJAX requests cannot be sent.

How do I allow cross-source access? You can use CORS to allow cross-source access. CORS is a part of HTTP that allows servers to specify which hosts can load resources.

How to cross domains

2.1 CROS Cross-domain Resource Sharing

Cross-domain resource sharing (CORS) is a mechanism that uses additional HTTP headers to tell browsers to allow Web applications on one source (domain) to access resources from different source servers.

Functions overview

Cross-domain resource sharing standards have added a new set of HTTP header fields that allow servers to declare which sources have access to which resources through browsers. 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 whether the server will allow the cross-domain 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). The cross-domain resource sharing (CORS) mechanism allows Web application servers to control cross-domain access and secure cross-domain data transfer. Modern browsers support the use of CORS in API containers, such as XMLHttpRequest or Fetch, to reduce the risk associated with cross-domain HTTP requests.

CORS access control

A simple request

Some requests do not trigger CORS precheck requests and are called “simple requests” (non-canonical definitions) :

  • use[GET](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Methods/GET) HEAD POSTRequest method
  • You can only set the following Headers (Headers set safe for CORS) manually: Accept Accept-Language Content-Language Content-Type DPR Downlink Save-Data Viewport-Width Width
  • Content-TypeYou can only set this parameter to the following three types:text/plain multipart/form-data application/x-www-form-urlencoded

Preview the request

In addition to the simple request above, cross-domain requests require a pre-checked request to be made using the OPTIONS method to determine whether the server will allow the actual request to be made. Such as the following request:

var invocation = new XMLHttpRequest();
var url = 'http://bar.other/resources/post-here/';
var body = '
      
      
       
        Arun
       
      ';

function callOtherDomain() {
  if(invocation) {
    invocation.open('POST', url, true);
    invocation.setRequestHeader('X-PINGOTHER'.'pingpong');
    invocation.setRequestHeader('Content-Type'.'application/xml'); invocation.onreadystatechange = handler; invocation.send(body); }}Copy the code



In the precheck request:

The first fieldAccess-Control-Request-MethodTell the server that the actual request will use the POST method.

The first fieldAccess-Control-Request-HeadersTell the server that the actual request will carry two custom request header fields:X-PINGOTHERContent-Type. The server then decides whether the actual request is allowed.



Precheck request response:

The first fieldAccess-Control-Allow-MethodsIndicates that the POST, GET, and OPTIONS methods are allowed to initiate requests.

The first fieldAccess-Control-Allow-HeadersIndicates that the x-Pingother and Content-Type fields are allowed in the request.

Finally, the header fieldAccess-Control-Max-AgeThe response time is 86400 seconds. The browser does not need to make another precheck request for the same request within the valid time.

Request with credentials

In general, browsers do not send identity credentials for cross-domain XMLHttpRequest or Fetch requests. To send credential information, you need to set the withCredentials flag of XMLHttpRequest to true to send Cookies to the server. In the case of pre-checking requests, set access-Control-allow-credentials: true in the response. For requests with credentials, the server must not set access-Control-allow-origin to *.

2.2 the json

JSONP is a scheme that utilizes script tags that are not restricted across domains.

The principle of

Insert one into the HTML

function jsonp({url, param, cb}){
  return new Promise((resolve, reject) = >{
    let script = document.createElement('script')
    window[cb] = function(data){
      resolve(data);
      document.body.removeChild(script) } params = {... params, cb}let arrs = [];
    for(let key in params){
      arrs.push(`${key}=${params[key]}`)
    }
    script.src = `${url}?${arrs.join('&')}`
    document.body.appendChild(script)
  })
}
Copy the code

disadvantages

Only GET requests are supported, but POST, PUT, and DELETE are not supported. Insecure and vulnerable to XSS attacks.

2.3 postMessage

The window.postMessage() method can safely implement cross-source communication.

grammar

/ * * *@param {any} Message will send data to other Windows *@param {string} TargetOrigin specifies which Windows can receive message events. The value can be either the string "*" * (for unrestricted) or a URI. *@param {Transferable} Transfer The Transferable object to be transferred */
otherWindow.postMessage(message, targetOrigin, [transfer]);
Copy the code

Send a message

var frame = document.querySelector('frame');
// Send a message to the embedded window
frame.contentWindow.postMessage('any type msg'.'http://iframe.example.com:8080/');
// You can also use onMessage to listen for returned messages
window.onmessage = function(event) {
  console.log(event.data);
};
Copy the code

Listen to the message

window.addEventListener("message", receiveMessage, false);

function receiveMessage(event) {
  // event.origin Specifies the targetOrigin parameter when calling postMessage or the origin of the message sender window
  if(event.origin ! = ="http://example.com:8080")
    return;
	
  // event.data An object passed from another window (message in postMessage).
  console.log(event.data);
  // event.source Is a reference to the window object that sent the message
  event.source.postMessage('received your msg.', event.origin);
  // ...
}
Copy the code

2.4 the window name

This approach is outrageous. Principle: No matter how the URL changes in the same window, the value of window.name is not affected. Implementation: Web application A, B homologous, C different sources, to pass C to A. Window. name will be set in C, window.name will be set in A, and window.name will be set in C, onload will be set in WINDOw. name, and then the SRC of iframe will point to B, so B can get window.name.

2.5 the location. The hash

Still outrageous.

The location. The hash features

The hash attribute is a readable and writable string that is the anchor part of the URL (starting with the # sign). Represents a location in a web page.

  • HTTP requests do not include #
  • Changing hash does not trigger page reloading
  • Changing the hash alters the browser’s access history
  • Onhashchange event, new in HTML 5 (Supported by Internet Explorer 8+, Firefox 3.6+, Chrome 5+, and Safari 4.0+)

Realize the principle of



2.6 Nginx Reverse Proxy

The principle of reverse proxy is to forward the front-end address and the back-end address to the same address using Nginx. Command:

  • start nginxStart nginx in the nginx directory
  • nginx -s reloadRestart the nginx

Client resolves cross-domain NginxNginx configuration

server
{
   listen 3003;
   server_name localhost;
   ## = / indicates that the exact match path is /, the real access is http://localhost:5500
   location = / {
       proxy_pass http://localhost:5500;
   }
   ## /no stands for urls that start with /no, including /no1,no/son, or no/son/grandson
   ## True access is the URL starting with http://localhost:5500/no
   ## if proxy_pass ends with/e.g. http://localhost:3000/; Match/no son, then the real match for http://localhost:3000/son
   location /no {
       proxy_pass http://localhost:3000;
   }
   ## /ok/ matches urls that start with ok exactly. /ok2 does not match. /ok/son does
   location /ok/ {
       proxy_passhttp://localhost:3000; }}Copy the code

The server resolves cross-domain NginxNginx configuration

server
{
    listen 3002;
    server_name localhost;
    location /ok {
        proxy_pass http://localhost:3000;

        # specify methods that are allowed across domains, * for all
        add_header Access-Control-Allow-Methods *;

        # precheck the cache of the command, if not cached will send two requests each time
        add_header Access-Control-Max-Age 3600;
        # Cookie requests require this field and set to true
        add_header Access-Control-Allow-Credentials true;

        # indicates that this domain is allowed to make cross-domain calls (the domain name and port from which the client sends the request)
        # $http_origin does not use * because requests with cookies do not support *
        add_header Access-Control-Allow-Origin $http_origin;

        # represents the dynamic retrieval of fields in the request header
        add_header Access-Control-Allow-Headers 
        $http_access_control_request_headers;

        The request will not be sent until the precheck command passes
        Check whether the type of request is a precheck command
        if ($request_method = OPTIONS){
            return 200; }}}Copy the code

This can achieve front-end pages and interfaces with different domain names. See Resources [6] for detailed analysis.

2.7 HTTP proxy — middleware

Vue framework uses node + Webpack + Webpack-dev-server agent interface across domains. In the development environment, since both the Vue rendering service and the interface proxy service are Webpack-dev-server, there is no need to set Headers cross-domain information between the page and the proxy interface. NodeJS http-proxy-middleware implements cross-domain proxy. The principle is roughly the same as nginx, which starts a proxy server to realize data forwarding. You can also set the cookieDomainRewrite parameter to modify the domain name in the cookie in the response header to write cookies to the current domain for interface login authentication.

Access across source document apis

Browsers have apis that allow documents to reference each other, such as iframe.contentWindow, window.parent, window.open(), and window.opener. These apis can get references to objects in other documents, but when two documents come from different sources, Access to that object (such as Window, Location) is limited. If you want Windows from two different sources to communicate further, you can use window.postMessage.

The resources

  • [1] MDN- Same Origin policy for browsers
  • [2] MDN-HTTP Access Control (CORS)
  • [3] MDN-window.postMessage
  • [4] Nuggets – Kaola Overseas Shopping front end team – cross-domain
  • [5] Nuggets — An_an16347 — Cross-domain summary
  • [6] CAaRrL- The same Origin Policy for browsers
  • [6] SegmentFault- QianduanZhou – Nginx For Solving cross-domain Problems