In order to reduce the site’s security risks, browser same-origin policy is introduced, the same-origin policy limits the load from the same origin document or script how to interact with resources from another source, this is an important security mechanism used for isolation of potential malicious files, the same-origin policy must ensure that the “deal + domain name + port” three are the same, Even if two different domain names point to the same IP address, they do not comply with the same origin policy. Therefore, cross-domain requests that do not comply with the same origin policy are generated. But cross-domain is not about the browser limiting the request, it’s about rejecting it, which means the request is sent to the server and returned from the server, but the browser rejects it.
The same origin policy restricts the following behaviors:
- Cookie, LocalStorage, and IndexDB cannot be read;
- DOM and JS objects are not available;
- AJAX requests cannot be sent.
Solutions to cross-domain problems include:
JSONP
Usually, in order to reduce the pressure of the Web server, we will separate static resources such as JS, CSS and IMG to another server with an independent domain name, and then load static resources from different domain names through the corresponding tags in HTML, which is allowed by the browser, JSONP is taking advantage of this vulnerability of the browser to achieve cross-domain.
<script>
var script = document.createElement('script');
script.type = 'text/javascript'; // Pass the parameter and specify the callback function as fn script.src ='http://www.domain.com:8080/login?user=admin&callback=fn'; document.head.appendChild(script); // The callback executes the functionfunction fn(res) {
alert(JSON.stringify(res));
}
</script>
Copy the code
The server returns the function call and passes the data as an argument to the browser:
fn({'status': true, code: 200, message: 'success'})
Copy the code
Background Node instance:
var querystring = require('querystring');
var http = require('http');
var server = http.createServer();
server.on('request'.function(req, res) {
var params = qs.parse(req.url.split('? ') [1]); var fn = params.callback; // jsonp returns setting res.writehead (200, {'Content-Type': 'text/javascript' });
res.write(fn + '(' + JSON.stringify(params) + ') ');
res.end();
});
server.listen('8080');
console.log('Server is running at port 8080... ');
Copy the code
Disadvantages of JSONP: Only get requests are implemented.
document.domain + iframe
This scheme is limited to cases where the primary domain is the same.
- Parent window :(www.domain.com/a.html)
<iframe id="iframe" src="http://child.domain.com/b.html"></iframe>
<script>
document.domain = 'domain.com';
var str = 'hello child';
</script>
Copy the code
- Child window :(child.domain.com/b.html)
<script>
document.domain = 'domain.com'; Alert (window.parent. STR); // hello child </script>Copy the code
window.postMessage
Window.postmessage () is an API in HTML5 XMLHttpRequest Level 2 that securely implements cross-domain communication. When the window.postMessage() method is called, a MessageEvent message is sent to the target window after all page scripts have executed (events set after the method, timeout events set before, and so on). The MessageEvent message has four attributes to note: The Message attribute indicates the type of message; The data attribute is the first argument to window.postMessage; The origin property represents the current state of the page when the window.postmessage () method is called; The source property records information about the window in which the window.postMessage() method is called.
- a.html(www.domain1.com/a.html)
<iframe id="iframe" src="http://www.domain2.com/b.html" style="display:none;"></iframe>
<script>
var iframe = document.getElementById('iframe');
iframe.onload = function() {
var data = {
name: 'aym'}; / / to send cross domain data domain2 iframe. ContentWindow. PostMessage (JSON. Stringify (data),'http://www.domain2.com'); }; // Accept domain2 returns data window.adDeventListener ('message'.function(e) {
alert('data from domain2 ---> ' + e.data);
}, false);
</script>
Copy the code
- b.html(www.domain2.com/b.html)
<script> // Receive data from domain1 window.addeventListener ('message'.function(e) {
alert('data from domain1 ---> ' + e.data);
var data = JSON.parse(e.data);
if(data) { data.number = 16; / / send back again after processing domain1 window. The parent. PostMessage (JSON. Stringify (data),'http://www.domain1.com'); }},false);
</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. Currently, all major browsers support CORS (IE8/9 requires the XDomainRequest object).
- Front-end Settings:
var xhr = new XMLHttpRequest(); // Ie8/9 requires window.XDomainRequest compatibility // The front end is set to enable cookie xhr.withCredentials =true;
xhr.open('post'.'http://www.domain2.com:8080/login'.true);
xhr.setRequestHeader('Content-Type'.'application/x-www-form-urlencoded');
xhr.send('user=admin');
xhr.onreadystatechange = function() {
if(xhr.readyState == 4 && xhr.status == 200) { alert(xhr.responseText); }};Copy the code
- Server Settings:
var http = require('http');
var server = http.createServer();
var qs = require('querystring');
server.on('request'.function(req, res) {
var postData = ' '; // Req.addListener ('data'.function(chunk) { postData += chunk; }); Req.addlistener ('end'.function() { postData = qs.parse(postData); // set res.writehead (200, {'Access-Control-Allow-Credentials': 'true'// The backend allows sending cookies'Access-Control-Allow-Origin': 'http://www.domain1.com'// Allow access to domain (protocol + domain + port) /* * Set the cookie to domain2, not domain1, because the backend can not write cookies (nginx reverse proxy can be implemented), * but as long as domain2 write cookie authentication once, All subsequent cross-domain interfaces can obtain cookies from domain2, so that all interfaces can cross-domain access */'Set-Cookie': 'l=a123456; Path=/; Domain=www.domain2.com; HttpOnly'// HttpOnly prevents javascript from reading cookies}); res.write(JSON.stringify(postData)); res.end(); }); }); server.listen('8080');
console.log('Server is running at port 8080... ');
Copy the code
WebSocket
To be exact, WebSocket is a network communication protocol, and its advantage over HTTP is that the client and the server can achieve two-way communication, while HTTP can only be initiated by the client, such as a real-time chat room, the client cannot know whether the server has new data, so it can only use “polling”. This approach undoubtedly has huge disadvantages, and WebSocket can solve these problems well. The biggest feature of WebSocket is that the server can actively send messages to the client, and the client can also actively send messages to the server, which is a real two-way equal dialogue. It also has the following characteristics:
- Based on TCP protocol, the implementation of the server side is relatively easy.
- It has good compatibility with HTTP protocol. The default ports are also 80 and 443, and the handshake phase uses HTTP protocol, so it is not easy to mask the handshake and can pass various HTTP proxy servers.
- The data format is relatively light, with low performance overhead and high communication efficiency.
- You can send text or binary data.
- There are no same-origin restrictions, and clients can communicate with any server.
- The protocol identifier is WS (or WSS if encrypted), and the server URL is the URL.
Client example :(example introduces socket.io)
The < div > user input: < inputtype="text"></div>
<script src="./socket.io.js"></script>
<script>
var socket = io('http://www.domain2.com:8080'); // Process socket.on('connect'.function() {// Listen for server message socket.on()'message'.function(msg) {
console.log('data from server: ---> '+ msg); }); // The listener closes the socket.on('disconnect'.function() {
console.log('Server socket has closed.');
});
});
document.getElementsByTagName('input')[0].onblur = function() {
socket.send(this.value);
};
</script>
Copy the code
Server example:
var http = require('http');
var socket = require('socket.io'); Var server = http.createserver (function(req, res) {
res.writeHead(200, {
'Content-type': 'text/html'
});
res.end();
});
server.listen('8080');
console.log('Server is running at port 8080... '); // Listen to socket connections socket.listen(server).on('connection'.function(client) {// Receive the message client.on('message'.function(msg) {
client.send('hello:' + msg);
console.log('data from client: ---> '+ msg); }); // Disconnect processing client.on('disconnect'.function() {
console.log('Client socket has closed.');
});
});
Copy the code