preface
First of all, what is the same origin policy? The same origin policy is a security policy proposed by Netspace. A homologous source is defined by the protocol, host, and port of a URL. If the three are consistent, the source is homologous.
What operations are allowed when different sources are involved?
<script>
Loads the Javascript<link>
Load the CSS<img>
Loading pictures<video><audio>
Loading Multimedia<object><embed><applet>
Load the plug-in<iframe>
Load anything- Links, jumps, form submissions
Which ones are not allowed?
- Cross-domain documents interact with each other using Javascript scripts with limited access to the API. For example, if an iframe comes from a different source than the parent page, it is not allowed to use Javascript to manipulate the parent page DOM
- Between different sources
XMLHttpRequest
Not allowed to
1. The modified source
The source of a page can be modified through document.domain, such as a page a.b.com embedded in iframec.b.com. In this case, you only need to set the document.domain of both pages to b.com.
2. Use a proxy
Cross domain is for the front end, the server is not cross domain this thing, so the background Settings, the front end access to a page of the same origin, and then the background requests the data to a different source of the page.
The front end
var xhr = new XMLHttpRequest();
var url = 'http://localhost:3000/api'; / / request to http://localhost:3000/api to get the data XHR. Open ('GET', url);
xhr.send(null);
xhr.onreadystatechange = () => {
if(xhr.readyState === xmlHttprequest.done && xhr.status === 200) {// If the request is successful text.innerhtml = xhr.response; }}Copy the code
Domain server
// nodeJs express
var proxy = require('http-proxy-middleware');
var app = express();
app.use('/api', proxy({target: 'http://localhost:3001/', changeOrigin: true}));
Copy the code
3.JSONP
Since
The front end
<script src="http://other.com/ajax.json?callback=myFunction"></script>
Copy the code
Cross-domain server
When the interface retrieves the callback, it passes the returned data to the callback as an argument and executes it.
// nodeJs express
app.get('/'.function (req, res) {
var callbackName = req.query.callback;
res.send(callbackName+"({'message': 'hello world'});");
})
Copy the code
disadvantages
- There are security issues
- Can only be GET requests
- The invocation is asynchronous
4.Web Messaging
This is an interface of HTML5, using the postMessage method in the interface, mainly used to exchange data between two Windows, can not be used to exchange data with the server.
otherWindow.postMessage(message, targetOrigin, [transfer]);
Copy the code
OtherWindow is a reference to the receiver window. Generally, it is in the following ways:
- window.iframe[0]
- document.getElementByTagName(‘iframe’)[0].contentWindow
- The reference returned by window.open
- Event. source Indicates the source of the received data
While Message supports almost all forms of data, transfer can be omitted
Usage:
/ / parent page document. GetElementByTagName ('iframe')[0].contentWindow.postMessage({"age": 10},'http://localhost:8080'); // Listen for data to return window.adDeventListener ('message'.function(e){
console.log(e)
});
Copy the code
// iframe
window.addEventListener('mesage'.function(e){
if(e.origin ! = ='http://localhost:8081') {return;
}
console.log(e);
e.souce.postMessage('hello world',e.origin)
})
Copy the code
5. Cross-domain resource sharing CORS
CORS needs to be supported by both the browser and the server. The key is the server. As long as the server implements the CORS interface, it can communicate across domains.
CORS classifies requests into two categories: simple and non-simple.
Conditions for non-simple requests:
- Request mode is “PUT”, “DELETE”
Content-type
The fields areapplication/json
A simple request
For simple requests, the browser adds an origin field in the header indicating the source (protocol + host + port) from which the request is sent. The server decides whether to approve the request or not based on this value. If Origin is not in the specified source, it returns a normal HTTP response, but if it does not contain access-Control-Allow-Origin, it knows that something has gone wrong and throws an error that is caught by the XMLHttpRequest onError callback.
This error cannot be identified by the status code, and may be 200
If the source is within the permitted range, the response is returned with several additional information fields.
Access-Control-Allow-Origin: http://localhost:3000
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: FooBar
Content-Type: text/html; charset=utf-8
Copy the code
Access-Control-Allow-Origin
Required field. If it is*
To receive requests for any domain name.Access-Control-Allow-Credentials
Optional field. CORS requests do not contain cookies and HTTP information by default, iftrue
, indicating that cookies can be included in the server license request. In addition to the server allowing requests with cookie and HTTP information, the client must also allow itvar xhr = new XMLHttpRequest(); xhr.withCredentials = true; Copy the code
Access-Control-Expose-Headers: FooBar
This field is optional. When CORS requests,XMLHttpRequest
The object’sgetResponseHeader()
The method only gets six basic fields:Cache-control, Content-language, Content-Type, Expires, Last-Modified, Pragma
. If you want to get the other fields, you have to be inAccess-Control-Expose-Headers
Specify inside. The above example specifies that,getResponseHeader('FooBar')
You can return the value of the FooBar field.
The front end
var xhr = new XMLHttpRequest();
var url = 'http://localhost:3001'; // Port 3001 is requested to obtain data
xhr.open('GET', url); // Establish a connection with port 3001
xhr.send(null); // The data sent to port 3001 is empty
xhr.onreadystatechange = (a)= > { // Call this function when the request status changes
if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) { // If the request succeedstext.innerHTML = xhr.response; }}Copy the code
Cross-domain server
// nodeJs express
var app = express();
app.get('/', (req, res) => {
res.set('Access-Control-Allow-Origin'.'http://localhost:3000'); // Set origin to allow cross-domain access to port 3000 (3001) res.send("Hello world");
});
Copy the code
Non-simple request
Non-simple requests differ in that there is an HTTP query request, called a “preflight” request, before formal communication.
The front end
var url = 'http://localhost:3001';
var xhr = new XMLHttpRequest();
xhr.open('PUT', url, true);
xhr.setRequestHeader('X-Custom-Header'.'value');
xhr.send();
Copy the code
The browser
When the browser realizes that this is a non-simple request, it automatically issues a precheck request.
OPTIONS /cors HTTP/1.1
Origin: http://api.bob.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...
Copy the code
The pre-checked request is OPTIONS, indicating that the request is for questioning.
Cross-domain server
After receiving the pre-check Request, the server checks the Origin, Access-Control-request-method, and access-Control-request-headers fields to confirm that cross-domain requests are allowed, and then responds
HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://api.bob.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Content-Length: 0
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain
Copy the code
Access-control-allow-methods indicates all cross-domain request Methods supported by the server.
If the precheck request passes, each subsequent CORS request is treated as a simple request.
disadvantages
Non-simple requests, the first request will be sent twice
6.WebSocket
Websockets are not homologous bound, so there is no cross-domain thing.
Basic usage:
var ws = new WebSocket("wss://echo.websocket.org");
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