The history of front-end development rings
- Server side rendering
- Client-side rendering (Same-origin policy)
- Client rendering (cross-domain solution)
- Semi-server Rendering (SSR)
Talk about your understanding of cross-domains
Cross-domain is mainly divided into three parts:
- The agreement is the same
- Domain name is the same
- The same port
If there is only one difference, then it is cross-domain
/ / address
http://www.baidu.comProtocol: HTTP://Domain name: www.baidu.com Port:8080(HTTP)443(HTTPS) The default port is omittedhttp:/ / www.baidu.com/login.html / / the same
http:/ / www.baidu2.com/login.html / / different sources, different domain name
http:/ / www.baidu.com:81/login.html / / different sources, different port
Copy the code
Homologous purpose
The goal is to keep user information safe and prevent malicious sites from stealing data, otherwise cookies can be shared. Some websites generally store some important information in cookies or LocalStorage, then if other websites can get access to this data, it is conceivable that there is no security at all.
limits
- Cookie, LocalStorage, and IndexDB cannot be read
- DOM not available
- AJAX requests cannot be sent
The three main ways do not work.
The solution
Scheme 1: CORS
It is common for nodeJS to configure CORS to allow cross-domain.
- Access-Control-Allow-Origin
- The * field is mandatory, indicating that requests of any domain name are allowed. When cookies need to be passed, you need to specify the domain name.
- Access-Control-Allow-Credentials
- The field is optional and defaults to false, indicating whether cookies are allowed to be sent. If yes, notify the browser to also enable the transfer of cookie values.
- Access-Control-Expose-Headers
- Field Optional. If you want the browser to get the getResponesHeader() other fields, specify them here.
- Access-Control-Request-Method
- A required field that is not set for simple requests, such as a PUT request.
- Access-Control-Request-Headers
- Specifies additional send header information to split the string with commas.
module.exports = {
//=>WEB service port number
PORT: 3001.//=>CROS cross-domain information
CROS: {
ALLOW_ORIGIN: 'http://127.0.0.1:5500'.ALLOW_METHODS: 'PUT,POST,GET,DELETE,OPTIONS,HEAD'.HEADERS: 'Content-Type,Content-Length,Authorization, Accept,X-Requested-With'.CREDENTIALS: true}}; app.use((req, res, next) = > {
const {
ALLOW_ORIGIN,
CREDENTIALS,
HEADERS,
ALLOW_METHODS
} = CONFIG.CROS;
res.header("Access-Control-Allow-Origin", ALLOW_ORIGIN);
res.header("Access-Control-Allow-Credentials", CREDENTIALS);
res.header("Access-Control-Allow-Headers", HEADERS);
res.header("Access-Control-Allow-Methods", ALLOW_METHODS);
req.method === 'OPTIONS' ? res.send('CURRENT SERVICES SUPPORT CROSS DOMAIN REQUESTS! ') : next();
});
Copy the code
Solution 2: Proxy
React, Vue and Argular are all engineered with WebPack. The most common type of local development is proxy proxy, which solves cross-domain problems.
The main principle is: the client requests data from the server. Webpack-dev-server creates a web service locally that is cognate with the client. The local service is actually a Node service that acts as an intermediate layer for the client to request data from the server and then return the data to the client.
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
mode: 'production'.entry: './src/main.js'.output: {
filename: 'main.[hash].min.js'.path: path.resolve(__dirname, 'build')},devServer: {
port: '3000'.compress: true.open: true.hot: true.proxy: {
'/': {
target: 'http://127.0.0.1:3001'.changeOrigin: true}}},// Configure the plugin for WEBPACK
plugins: [
new HtmlWebpackPlugin({
template: `./public/index.html`.filename: `index.html`}})];Copy the code
Scheme 3: JSONP
This is not cross-domain. So, the front-end code to write a script SRC = http://localhoost:80/list? Callback =func, which sends the link to the server. However, the function passed to the server must be a global function. When the server receives the request, it returns the value callback to the client. The client retrieves the specified format string returned by the server. Discover that it is the local func global function that executes and passes data to this function.
However, this approach has a drawback, that is, only get request, and insecure, as long as the server support, anyone can call.
The following is a handwritten implementation of JSONP
function jsonp(url = "", callback) {
let script;
// Mount the passed callback function globally
let name = `jsonpThe ${new Date().getTime()}`;
window[name] = data= > {
// Get the result from the server
document.body.removeChild(script);
delete window[name];
callback && callback(data);
};
/ / processing the URL
url += `${url.includes('? ')?'&' : '? '}callback=${name}`;
// Send the request
script = document.createElement('script');
script.src = url;
document.body.appendChild(script);
}
jsonp('http://127.0.0.1:1001/list? lx=1'.result= > {
console.log(result);
});
jsonp('https://matchweb.sports.qq.com/matchUnion/cateColumns?from=pc'.result= > {
console.log(result);
});
Copy the code
Scheme 4: Nginx reverse proxy
This is what the back end needs to do, and I’m actually not very familiar with it, the general configuration.
server { listen 80; Server_name 192.168.161.189; #charset koi8-r; #access_log logs/host.access.log main ; Location {proxy_pass HTTP: // 192.168.161.189:8070; root html; index index.html index.html; }}Copy the code
What is agency?
Since the Proxy is cross-domain, Proxy Server is a very important point. The Proxy here refers to the Server Proxy, which is a very important Server security function and a very common design pattern to isolate different modules and decouple modules.
Why is agency counter-rational?
Nginx could hand out the user’s request to the free server, then the server returned to their service to the load balancing device, then speak the server load balancing machine service returns to the user, so we don’t know why the service which is a server sends out, it is good to hide the server. There is an incisive saying: “Reverse proxy is flow divergence, proxy is flow convergence.”
Solution 5: POST MESSAGE
A.html
< iframe id = "iframe SRC =" http://127.0.0.1:1002/B.html "frameborder =" 0 "style =" display: none;" > < iframe > iframe. Onload = function () {iframe. ContentWindow. PostMessage (' message ', 'http://127.0.0.1:1002/'); }} window. onMessage = function (ev) {console.log(ev.data); }Copy the code
B.html
window.onmessage = function (ev) {
// console.log(ev.data);
//=>ev.source:A
ev.source.postMessage(ev.data + '@@@', '*');
}
Copy the code
Option 6: Iframe-based cross-domain solution 1 — locaction.hash
How it works: Iframe can be used to transfer values between different fields, and location.hash can carry parameters, so iframe is used as a bridge between different fields.
A Domain name Page
var iframe = document.createElement('iframe')
iframe.src = 'http://www.B.com:80/hash.html'
document.body.appendChild(iframe)
window.onhashchange = function () {
/ / handle hash
console.log(location.hash)
}
Copy the code
B Domain name Page
var xhr = new XMLHttpRequest()
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
var res = JSON.parse(xhr.responseText)
console.log(res.msg)
parent.location.href = `http://www.A.com:80/a.html#msg=${res.msg}`
}
}
xhr.open('GET'.'http://www.B.com:80/json'.true)
xhr.send(null)
Copy the code
disadvantages
- Iframe can solve the problem, but security risks are still important.
- Hash pass-throughs are cumbersome to handle.
Solution 7: Iframe-based cross-domain solution 2 — window.name
The principle is the same as the above method, but the difference is that window.name can pass more than 2MB of data.
A Domain name Page
var iframe = document.createElement('iframe')
iframe.src = 'http://www.B.com:80/name.html'
document.body.appendChild(iframe)
var times = 0
iframe.onload = function () {
if (times === 1) {
console.log(JSON.parse(iframe.contentWindow.name))
destoryFrame()
} else if (times === 0) {
times = 1}}// After the data is retrieved, the iframe is destroyed to free memory;
function destoryFrame() {
document.body.removeChild(iframe);
}
Copy the code
B Domain name Page
var xhr = new XMLHttpRequest()
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
window.name = xhr.responseText
location.href = 'http://www.A.com:80/a.html'
}
}
xhr.open('GET'.'http://www.B.com:80/json'.true)
xhr.send(null)
Copy the code
And so on