The same-origin policy
Browsers have the same origin policy. If they have different protocol domain names and ports, they cannot access resources from each other
Achieve cross-domain
- jsonp
- cors
- postMessage
- Window.name
- http-proxy
- Document.domain
JSONP
- Declare a function locally
function show(data){
console.log(data)
}
Copy the code
- The latter section returns the execution of the function
<script src="https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=lol&cb=show"></script>// cb is the name of the executive function that returns the thicknessCopy the code
/ / the back-end returns show ({p: false q: "lol" s: (10) [" lol website ", "lol mobile game", "turn lol area", what do you mean "lol", "lol half price", "spring" lol ", "turn lol area system"]})Copy the code
Encapsulate a generic JONSP function
/ / use
jsonp({
url:'xxx'.params: {wd:'xxx'},
cb:'xx'
}).then(res= >console.log(data))
Copy the code
let jsonp = ({url,params,cb}) = >{
return new Promise((resolve,reject) = >{
1. Create a script tag
let script = document.createElement('script')
//3. Mount cb to the global system. The back-end system returns CB data
window[cb]=function(data){
resolve(data)
//4. Remember to add to script delete
script.remove()
}
// convert params and cb to wd=xxx&cb= XXXparams = {... params,cb}let arr = []
for(let key in params){
arr.push(`${key}=${params[key]}`)
}
script.src=url+'? '+arr.join('&')
document.body.appendChild(script)
})
}
Copy the code
The disadvantage of the json
- Only GET requests can be sent, but post, PUT, and DELETE are not supported
- Unsafe, reference links to websites that may cause harm if they return an attack code, XSS attacks, not supported
Node provides JSONP functionality under emulation
let express = require('express')
let app = new express()
app.get('/say'.function(req,res){
let {wd,cb}=req.query
res.end(`${cb}(' returned data ') ')
})
app.listen(3000.function(){console.log('start')})
Copy the code
cors
This is a back-end solution that can be simulated using Node
Start two servers, one 3000 port and one 4000 port
Port 3000 starts a web page to access resources of port 4000
const express = require('express');
let app = express();
// Provide access to the resources in this directory as static resources
app.use(express.static(__dirname));
app.listen(3000.function () {
console.log('3000 start');
});
Copy the code
// index.html
<script>
let xhr = new XMLHttpRequest();
xhr.open('get'.'http://localhost:4000/say');
xhr.onreadystatechange = function () {
if(xhr.readyState === 4 && 300 >= xhr.status&&xhr.status >= 200) {
console.log(xhr.response); }}; xhr.send();</script>
Copy the code
Browser input: localhost: 3000 / index. HTML, warns cross-domain problem
And the port: 4000 service receives a request to port 3000, but the returned content is blocked by the browser
Access-control-allow-origin does not Allow http://localhost:3000 to Access resources, yes
Set the allowed domain name
// Set a whitelist of allowed domain names
let whiteList = ['http://localhost:3000'];
app.use(function (req, res, next) {
// Get the origin of the request
let origin = req.headers.origin;
if (whiteList.includes(origin)) {
// If it is in the whitelist, access is allowed
res.setHeader('Access-Control-Allow-Origin', origin);
}
next();
});
Copy the code
Sets the request mode to allow access
But this method only allows simple requests like GET, POST,head, or put
xhr.open('put'.'http://localhost:3000/say')
Copy the code
app.put('/say'.function(req,res){
res.end('post request')})Copy the code
The browser has reported an error and we need the backend Settings to allow PUT requests
app.use(function(req,res){
res.setHeader('Access-Control-Allow-Methods'.'PUT')// Remember uppercase
})
Copy the code
Sets the request headers that need to be allowed access
What if we add some information to the request header,
xhr.setRequestHeader('name'.'huzhiwu')
Copy the code
The browser warns that the backend is required to allow that request header
But port 4000 can accept this request header
Sets the allowed headers
res.setHeaders('Access-Control-Allow-Headers'.'name')
Copy the code
Set the Max – age
We print the method for each request in port 4000’s service
app.use(function(req,res){
console.log(req.method)
})
Copy the code
When you refresh your browser, you’ll notice. Port 4000 prints two methods
Options means that when the browser discovers cross-domain, it will send a pre-check request to the server. This method returns methods that allow access. If the request method is not in methods, an error will be reported
So if we’re sending one request at a time, and we’re actually sending two requests, it’s a little bit more expensive, so if we don’t change our method very often, we can make it
It is enough for the browser to pre-check once at a time
req.setHeader('Access-Control-Max-Age'.5)/ / unit of seconds
Copy the code
Allows cookies to be carried across domains
let xhr = new XMLHttpRequest();
xhr.open('put'.'http://localhost:4000/say');
document.cookie='name=huzhiwu'
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && 300 >= xhr.status && xhr.status >= 200) {
console.log(xhr.response); }}; xhr.send();Copy the code
// Server with port 4000
app.use(function(req,res){
console.log(req.headers)
})
Copy the code
We found no cookies we were carrying
Add in the Ajax request
xhr.withCredentials = true;
Copy the code
Browser error again
Allow cookies to be carried across domains in Node
res.serHeader('Access-Control-Allow-Credentials')
Copy the code
Allows the browser to get the HEADERS returned by the server
app.put('/say'.function(req,res){
res.setHeader('name'.'huzhiwu')
res.end('put')})Copy the code
let xhr = new XMLHttpRequest();
xhr.open('put'.'http://localhost:4000/say');
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && 300 >= xhr.status && xhr.status >= 200) {
console.log(xhr.getResponseHeader('name')); }}; xhr.send();Copy the code
The browser reported an error again
The browser doesn’t think the request header the server returns to you is safe and won’t give it to you
Set in Node
res.setHeader('Access-Control-Expose-Headers'.'name')
Copy the code
summary
// Allow which source can access me
res.setHeader('Access-Control-Allow-Origin',origin)
// Allow that method to access me
res.setHeader('Access-Control-Allow-Methods'.'PUT')
// Precheck the survival time
res.setHeader('Access-Control-Max-Age'.5)/ / unit of seconds
// Allow headers to be carried
res.setHeader('Access-Control-Allow-Headers'.'name')
// Allow the browser to get the headers returned by the server
res.setHeader('Access-Control-Expose-Headers'.'name')
Copy the code
PostMessage cross-domain
Pages communicate with pages nested in iframe
Enable services A and B respectively on ports 3000 and 4000
//a.js b.js
const express = require('express');
const app = express();
app.use(express.static(__dirname));
app.listen(4000/3000.function () {
console.log('4000/3000 start');
});
Copy the code
Put page A on port 3000 and page B on port 4000
Reference page A in page B
<body>
<iframe src='http://localhost:3000/a.html' id='aIframe' onload='load()'>
</iframe>
<script>
function load(){
let frame = document.getElementById('aIframe')
// Send a message to the window of the page nested in the iframe
// The second argument is origin
frame.contentWindow.postMessage('Hello, THIS is PAGE B'.'http://localhost:3000/a.html')}// Page B listens for information from page A
window.onmessage=function(e){
console.log(e.data)
}
</script>
</body>
Copy the code
Listen for information on page B on page A
window.onmessage=function(e){
console.log(e.data)
// After receiving the message, send the message to page B,
e.source.postMessage('Hello, this is page A', rigin)}Copy the code
The browser open http://localhost:4000/b.html
summary
Send a message
window.postMessage('information'The orign)Copy the code
Receive information
window.onmessage=function(e){
console.log(e.data)
}
Copy the code
Window. The name across domains
Window.name is an empty string by default. We can store information in name and access it across domains
- A and B are symtopic
http://localhost:3000
- C is for another domain
http://localhost:4000
- Page A uses iframe to reference C and iframe to reference B.
- The window.name of page C can be obtained from page A
Start two servers with ports 3000 and 4000 respectively
C page
<script>
window.name='I'm c page'
</sctript>
Copy the code
A page
<body>
<iframe src='http://localhost:4000/c.html' id='frame' onload='load()'>
</iframe>
<script>
let first=true
let frame = document.getElementById('frame')
function load(){
// Immediately after the first load, transfer the frame SRC to the same source
if(first){
frame.src='http://localhost:3000/b.html'
first=false;
}else{
// Under the same name, you can access name
console.log(frame.contentWindow.name)
}
}
</script>
</body>
Copy the code
http-proxy
Proxies can be used when network requests cross domains.
Server access servers have no cross-domain problems. So, what we do is we use the proxy browser in the middle to send requests to the target browser.
- Enable the services for ports 3000 and 4000 respectively
- A The page is stored in port 3000
- Page A sends the request, and the server at port 3000 forwards the request to port 4000
a.js
const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');
// Forward the request to another server
const apiProxy = createProxyMiddleware('/say', {
target: 'http://localhost:4000'});const app = express();
app.use(express.static(__dirname));
app.use(apiProxy);
app.listen(3000.function () {
console.log('3000 start');
});
Copy the code
b.js
const express = require('express');
const app = express();
app.use(express.static(__dirname));
app.get('/say'.function (req, res) {
res.end('THIS is information from server B');
});
app.listen(4000.function () {
console.log('4000 start');
});
Copy the code
<script>
let xhr = new XMLHttpRequest();
xhr.open('get'.'http://localhost:3000/say');
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && 300 >= xhr.status && xhr.status >= 200) {
console.log(xhr.response); }}; xhr.send();</script>
Copy the code
The HTTP proxy – middleware see https://github.com/chimurai/http-proxy-middleware for more parameters
Document. The domain across domains
For example, www.video.baidu.com and www.map.baidu.com are two secondary domain names,
// www.map.baidu.com
<body>
<script>
window.name='huzhiwu'
</script>
</body>
// www.video.baidu.com
<body>
<iframe src='www.map.baidu.com' id='frame' onload='load'>
</iframe>
<script>
function load(){
let frame = document.getElementById('frame')
console.log(frame.contentWindow.name)// Cross-domain access failed
}
</script>
</body>
Copy the code
Because there is no cross-domain access,
But as long as the two secondary domain name add document.domain=’baidu.com’ can access each other
code
Github.com/huzhiwu1/Sa…
conclusion
Author: Hu Zhiwu
Time: 2020/05/06
If you like it, please give it a thumbs up. If you have any mistakes, please correct them