Writing in the front

Cross domain is homologous request: ruanyifeng.com/blog/2016/04/same-origin-policy.html

Cross-domain concept: Cross-domain refers to a document or script in one domain trying to request resources in another domain (for example, obtaining a page from site A and then accessing resources in site B on this page)

Source: Same protocol, same domain name, and same port. On the contrary, different sources; There’s no cross-domain in homology. Even if two different domain names point to the same IP address, they are not identical.

The same origin is the core and most basic security function of the browser. Without the same origin policy, the browser is vulnerable to XSS and CSFR attacks

Homologous restriction:

1.Cookie, LocalStorage, and IndexDB cannot be read2.DOM and Js objects are not available3.AJAX requests cannot be sentCopy the code

Note: Browsers do not restrict access to other domain names through script tags. (For example, when jquery library is introduced, script tag is cross-domain, but browser has no restrictions)

// Cross-domain exampleThe client accesses it with an XMLHttpRequest object`http://www.tianmao.com`, Tmall returns to the client at`http://www.tianmao.com`In the domain page, there is a js code request` http://www.jd.com `, at this time request JINGdong website, will occur cross-domain, because the browser has security restrictions, the request is sent, but the data can not come back; Browsers have restrictions on cross-domain requests for XMLHttpRequest objects, but not script tagsCopy the code

Nine solutions across domains:

1, cross domain via JSONP (script tag cross domain)2,document.domain + iframe Cross-domain3And the location. The hash + iframe4,window. Name + iframe Cross-domain5, the postMessage across domains6Cross-domain resource sharing (CORS)7, nginx proxy across domains (intermediate server forwarding)8Nodejs middleware proxy across domains (intermediate server forwarding)9WebSocket protocol cross-domain (the new protocol is not cross-domain restricted)Copy the code

Cross-domain granddaddy

Initially for cross-domain, you need to manually change the host. For example, the data interface at the back end of the local request is HTTP :api.xx.com/getData, but the direct access by the local browser is cross-domain. At this time can be a web service in the local address HTTP: 127.0.0.1:1111 / index. HTML, then change the host file, make the front-end code request in api.xx.com interface, make the request to 127.0.0.1:1111 service address. This allows the local server to access the remote server without cross-domain because cross-domain does not exist between back-end servers

jsonp

Script, IMG, link, iframe, etc., do not have restrictions on cross-domain requests; And all resource file requests here are GET requests

The underlying principle of JSONP is to send requests through script tags, taking advantage of the fact that

Jsonp cross-domain disadvantages:

  1. Only supportgetRequest mode. Because it uses the script tag to send the request; And the server side needs to do the processing, the client side needs to do the processing; If too many parameters are passed across domains, this approach is not advisable.
  2. Not safe. Server returns what the browser executes directlyfunc("data")Whatever is returned, the browser will execute it directly. If it returns a Trojan, then… ; And the data is passed through the URL question mark parameter, easy to be hijacked by the URL.

Advantages: JSONP has good compatibility and can be used to solve the problem of cross-domain data access in mainstream browsers

Comparison between JSONP and AJAX: JSONP is the same as AJAX in that the client sends a request to the server and obtains data from the server. But AJAX is a same-origin policy, JSONP is a non-same-origin policy (cross-domain request)

<! - the sample1: The server returned data, but reported a syntax errorSyntaxErrorBecause we request data in script mode, so the server returns data, the client will parse it in JS mode.<script>
    document.querySelector('input').onclick = function(){
        var script = document.creatElement("script");
        script.src = "http://www.jd.com/index.php";
        document.body.appendChild(script);
    }
</script><! - the sample2You can pass the client's callback function as an argument to the server to return the string form of the function call.<script>
    function getInfo(data){
        // Process the data returned by the server
        console.log(data);
    }
    document.querySelector('input').onclick = function(){
        var script = document.creatElement("script");
        script.src = "http://www.jd.com/index.php?callback=getInfo";   // Require the server to return "getInfo "so that the client can parse it into a function call in JS code
        document.body.appendChild(script);
    }
</script>
Copy the code

CORS cross-domain resource sharing

For common cross-domain requests, only access-Control-allow-origin is required on the server. This parameter is not required on the front end. If cookie is required, access-Control-allow-origin is required on both the front and back ends.

Note that due to the restriction of the same-origin policy, the cookie read is the cookie of the domain where the cross-domain request interface resides, not the current page.

Compatibility: Currently, all browsers support this functionality (IE8+ : IE8/9 requires the use of XDomainRequest objects to support CORS), and CORS has become a mainstream cross-domain solution.

CORS cross-domain principle: such as the client 127.0.0.1:5000 / index. The HTML page Access server-side 127.0.0.1:3000 address, the cross-domain occur, the server can be in the response headers, set up the Access – Control – Allow – Origin: 127.0.0.1:5000: allows clients at 127.0.0.1:5000 to access it.

Note: In cORS cross-domain mode, the client will first make an options exploratory request to the server. When the server sees the request, it will return a request indicating that it agrees to the subsequent cross-domain request.

Key steps:

1.Client side (Ajax/FETCH sends requests)2.The server sets headers (such as domain names allowed across domains, methods allowed across domains, cookie credentials allowed across domains)3.The server also needs to process options exploratory requestsCopy the code

Disadvantages:

  1. Access-Control-Allow-OriginCan only be set to* / A specific domain name address,; If set to*Number cannot carry cookies. Since all sources can request cookies, they are passed around, and browsers do not allow cookies for security reasons.

http-proxy

Juejin. Cn/post / 691494…

Generally, it is configured in webpack or webpack-dev-server. The idea of proxy is basically to start an intermediate Webserver, the front end of the first request to the Webserver, and then the webserver request back end; Because there is no cross-domain between services.

// src/client.js
// Simulate test client
// Note that http://localhost:8080 is requested by default, but http://localhost:3000 is started in server.js, so it cannot be accessed across domains.
// To provide an idea, you can first ask the client to send the request to webPack devServe, devServer is http://localhost:8080 service, Then have devServer forward to the http://localhost:3000 service of server.js
let xhr = new XMLHttpRequest()
xhr.open('GET'.'/api/user'.true)
xhr.onload = () = > {
  console.log(xhr.response);
}
xhr.send()


// src/server.js 
let express = require('express')
let app = express()

app.get('/api/user'.(req, res) = > {
  res.send("I'm the return message from the server hello")
})
app.listen(3000.'127.0.0.1')  // The IP address can be omitted, and the default listener is localhost



// webpack.config.js
devServer: {
  proxy: {
    '/api': 'http://localhost:3000'   Port is not set. DevServer starts at 8080 by default. In this case, http://localhost:8080 domain names that start with/API will be proxy to http://localhost:3000 domain names}}Copy the code

Nginx reverse proxy

The core idea is to make a server to do a layer of intermediate proxy

For example, the address of the local access back end is www.xxx.com/api, but cross-domain can occur. You can have a local nginx, a proxy service in nginx, and then have the local service directly request the NG proxy service, which then forwards the request to the remote server.

// client.jsNormal request remote service: www.xxx.com/api Change the local code request to ng listening address:` ` 127.0.0.1:80 / API, which accesses ng and then calls`locaiotn /api/`, the ng proxy service will request it`http:www.xxx.com/api`


// Configure nginx.conf locally
server: {
    listen:80
    server_name: 127.0. 01.

    locaiotn /api/ {
        proxy_pass   http:www.xxx.com/api
    }
}
Copy the code

postMessage

Juejin. Cn/post / 694794…

A new API was introduced: cross-document Messaging API.

Because two Windows are not homologous pages, there is no way to communicate and share cookies, storage, etc. The window.postMessageAPI adds a window.postMessage method to window objects, allowing cross-window communication regardless of whether the two Windows are identical.

For example, the parent window aaa.com sends a message to the child window bbb.com and calls the postMessage method.


API’s brief introduction:

  1. window.postMessage('Hello World! ', 'http://bbb.com');

The first argument to the postMessage method is the specific message content, and the second argument is the origin of the window that received the message, i.e., protocol + domain + port. You can also set this parameter to *, which indicates that the domain name is not limited and the message is sent to all Windows.

  1. Both parent and child Windows can passmessageEvent to listen for messages from the other party.
window.addEventListener('message'.function(e) {
  console.log(e.data);
},false);
Copy the code

The event object for the message event provides the following three properties:

Event. source: indicates the window for sending messages. Event. Origin: indicates the website for sending messagesCopy the code

Let’s assume that I have two pages, A and B, and the purpose is to click the postMessage button in the WINDOW OF B and receive the message sent to page A

/ / A page
<script>
  function test() {
    let op = window.open('b.html'.'_blank'); 
    function receiveMessage(event) {
      console.log('event', event);
    }
    op.addEventListener("message", receiveMessage, false); 
  }
</script>
<body>
  <div>
    <button onClick="test()">open</button>
  </div>
</body>
Copy the code
/ / B page
<script>
  function post() {
    window.postMessage("hi there!", location.origin);
  }
  function receiveMessage(event) {
    console.log('event', event)
  }
  window.addEventListener("message", receiveMessage, false);
</script>
<body>
  <div>
    <button onClick="post()">postMessage</button>
  </div>
</body>
Copy the code

webSocket

Juejin. Cn/post / 684490…

www.ruanyifeng.com/blog/2017/0…

People who are new to WebSocket ask the same question: Why do we need another protocol when we already have HTTP? What good can it do?

The answer is simple, because HTTP has a flaw: traffic can only be initiated by the client, and data cannot be pushed from the server to the client. Websocket is a full-duplex communication protocol that can not only send data from the client to the server, but also actively push data from the service to the client.

Websocket is a network communication protocol that prefixes ws:// (unencrypted) and WSS :// (encrypted). Browsers have no cross-domain restrictions on this communication protocol.

/ / the websocket characteristics1) based on TCP protocol, the implementation of the server side is relatively easy. (2) has good compatibility with THE HTTP protocol. The default port is also80and443And the handshake phase uses HTTP protocol, so the handshake is not easy to shield, can pass a variety of HTTP proxy server. (3) Data format is relatively light, low performance overhead, efficient communication. (4) can send text or binary data. (5) There is no same-origin restriction, and clients can communicate with any server.Copy the code
ws://example.com:80/some/path
Copy the code

// client.js

// New WebSocket("wss://echo.websocket.org") will connect to the wss://echo.websocket.org server.
var ws = new WebSocket("wss://echo.websocket.org");

// Successful callback
ws.onopen = function(evt) { 
  console.log("Connection open ..."); 
  ws.send("Hello WebSockets!");
};

ws.onmessage = function(evt) {
  console.log( "Received Message: " + evt.data);
  ws.close();
};

ws.onclose = function(evt) {
  console.log("Connection closed.");
};      
Copy the code