6 cross domain solutions

Homologous strategy

Browsers have the same origin policy, and the protocol domain name ports are different, so they can't access each other's resources

Cross domain implementation

  • jsonp
  • cors
  • postMessage
  • Window.name
  • http-proxy
  • Document.domain

JSONP

  1. Declare a function locally
function show(data){
  console.log(data)
}
Copy code
  1. The latter segment returns the execution of this function
<script src="https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=lol&cb=show"></script>
//cb is the name of the execution function returned by the thickness
 Copy code
//Back end will return
show({
    p: false
    q: "lol"
    s: (10) ["lol Official website", "lol Mobile Games", "lol Transfer zone", "lol What do you mean?",
    "lol Half price", "lol Spring competition", "lol Transfer system"]
})
Copy code

Encapsulate a general jonsp function

//Use
jsonp({
  url:'xxx',
  params:{wd:'xxx'},
  cb:'xx'
}).then(res=>console.log(data))
Copy code
let jsonp = ({url,params,cb})=>{
 return new Promise((resolve,reject)=>{
    //1. Create a script tag
   let script = document.createElement('script')
   //3. Mount the cb to the global, the back end will return cb (data), and receive the data return data
   window[cb]=function(data){
     resolve(data)
   //4. Remember to add to script delete
     script.remove()
   }
   //2. Convert params and cb to WD = XXX & cb = XXX
   params = {...params,cb}
   let arr = []
   for(let key in params){
     arr.push(`${key}=${params[key]}`)
   }
   script.src=url+'?'+arr.join('&')
   document.body.appendChild(script)
 })
}
Copy code

Disadvantages of jsonp

  1. Only get requests can be sent, post put delete is not supported
  2. Unsafe, if the website that references the link returns a piece of attack code, it may cause harm, xss attack, not supported

Provide JSON function under node simulation

let express = require('express')
let app = new express()
app.get('/say',function(req,res){
	let {wd,cb}=req.query
	res.end(`${cb}('Data returned')`)
})
app.listen(3000,function(){console.log('start-up')})
Copy code

cors

This is a back-end solution, which can be simulated by node s

Start two servers, a 3000 port and a 4000 port

3000 port starts a web page to access the resources of 4000 port in the web page

const express = require('express');
let app = express();
//Provide access to resources in this directory in the form of static resources
app.use(express.static(__dirname));
app.listen(3000, function () {
	console.log('3000 start-up');
});
Copy 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 code

Browser input: localhost:3000/index.html, will warn cross domain problems

And port: the service of port 4000 receives the request of port 3000, but the returned content is blocked by the browser

Tip: access control allow origin does not allow http://localhost:3000 to access resources. You can

Set the domain name allowed to access

//Set the white list of domain names allowed to access
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 on the white list, he is allowed to visit
        res.setHeader('Access-Control-Allow-Origin', origin);
    }
    next();
});
Copy code

Set how access is requested

But this method only allows simple requests such as get, post and head. If it is put

xhr.open('put','http://localhost:3000/say')
Copy code
app.put('/say',function(req,res){
  res.end('post request')
})
Copy code

The browser reports an error. We need to set the backend to allow put requests

app.use(function(req,res){
    res.setHeader('Access-Control-Allow-Methods','PUT')//Remember to capitalize
})
Copy code

Set request headers that need to be accessible

If we add some information to the request header,

xhr.setRequestHeader('name','huzhiwu')
Copy code

The browser warns that the back end needs to allow that request header

But port 4000 can accept this request header

Set allowed request headers

res.setHeaders('Access-Control-Allow-Headers','name')
Copy code

Set Max age

We print the method of each request in the service of port 4000

app.use(function(req,res){
	console.log(req.method)
})
Copy code

When you refresh the browser, you will find. Port 4000 prints two method s

options is that when a browser discovers a cross domain, it will first make a pre check request to the server. This method returns the methods allowed to access. If the request method is not in methods, an error will be reported. If it exists, the real request will be sent

In this way, one request is sent at a time, and two requests are actually sent, which consumes performance. If our method does not change frequently, we can

Browser pre check once in a period of time is enough

Req.setheader ('Access control Max age ', 5) / / unit: Second
 Copy code

Allow cookie s 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 code
// Server on port 4000
app.use(function(req,res){
  console.log(req.headers)
})
Copy code

We found no cookie s We had

Add in ajax requests

xhr.withCredentials = true;
Copy code

The browser reported another error

Set in node to allow cookie s to be carried across domains

res.serHeader('Access-Control-Allow-Credentials')
Copy code

Allow browser to get headers returned by server

app.put('/say',function(req,res){
  res.setHeader('name','huzhiwu')
  res.end('put')
})
Copy 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 code

Browser error again

The browser thinks that the request header returned to you by the server is not safe and will not be obtained for you

Set in node

res.setHeader('Access-Control-Expose-Headers','name')
Copy code

Summary

//Which sources are allowed to access me
res.setHeader('Access-Control-Allow-Origin',origin)
//Allow that method to access me
res.setHeader('Access-Control-Allow-Methods','PUT')
//Pretest survival time
res.setHeader('Access-Control-Max-Age',5)//Unit second
//Allowed headers
res.setHeader('Access-Control-Allow-Headers','name')
//Allow browser to get headers returned by server
res.setHeader('Access-Control-Expose-Headers','name')
Copy code

postMessage cross domain

Pages communicate with pages nested in iframe

Open a and B services respectively, with port numbers of 30004000

//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-up');
});
Copy code

a page on port 3000, b page 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 information to window s of pages nested in iframe
  	    //The second parameter is origin
  	    frame.contentWindow.postMessage('Hello, I am b page','http://localhost:3000/a.html')
    }
    //b page listens for information from a page
    window.onmessage=function(e){
      console.log(e.data)
    }
  </script>
</body>
Copy code

Listen to the information of page b in page a

window.onmessage=function(e){
  console.log(e.data)
  //Send a message to page b after receiving the message,
  e.source.postMessage('Hello, I am a page',e.origin)
}
Copy code

The browser opens http://localhost:4000/b.html

Summary

Send message

window.postMessage('Information ', orign)
Copy code

Receiving information

window.onmessage=function(e){
  console.log(e.data)
}
Copy code

window.name cross domain

window.name is an empty string by default. We can store information in name and access it across domains

  1. a and b are the same domain http://localhost:3000
  2. c is http://localhost:4000 for another domain
  3. a page first iframe references c, then iframe references b,
  4. a page can get the window.name of c page

Open two servers, 3000 and 4000 ports respectively

c page

<script>
	window.name='I am c page'  
</sctript>
Copy 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(){
  	//After the first loading, immediately transfer the src of frame to the same source
  	if(first){
  	    frame.src='http://localhost:3000/b.html'
  	    first=false;
  	}else{
  	    //From the same source, you can access name
  	    console.log(frame.contentWindow.name)
  	}
        
    }
  </script>
</body>
Copy code

http-proxy

When network requests cross domain, you can use a proxy.

There is no cross domain problem for server access server. Therefore, our approach is to use the intermediate proxy browser to send requests to the target browser.

  1. Open 3000 port and 4000 port services respectively
  2. a page in port 3000
  3. Page a sends the request, and the 3000 port server forwards the request to the 4000 port
a.js
const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');
//Forward 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-up');
});
Copy code
b.js
const express = require('express');
const app = express();
app.use(express.static(__dirname));
app.get('/say', function (req, res) {
	res.end('I am b Server information');
});
app.listen(4000, function () {
	console.log('4000 start-up');
});
Copy 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 code

For more parameters of HTTP proxy middleware, see https://github.com/chimurai/http-proxy-middleware

document.domain cross domain

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 not available
  }
  </script>
</body>
Copy code

Because cross domain access is not available,

But as long as you add a document.domain='baidu.com 'to the two secondary domain names, you can access each other

Code

github.com/huzhiwu1/Sa...

epilogue

Author: Hu Zhiwu

Time: May 6, 2020

If you like it, please like it. If there are any mistakes, please correct them

Tags: github Mobile Spring JSON

Posted on Thu, 07 May 2020 00:56:33 -0400 by river001