preface
Front – and back-end data interactions often encounter cross-domain requests, what cross-domain is, and how cross-domain works, which I thought I should document.
I. What is cross-domain?
1. What is the same-origin policy and its restrictions?
- The same-origin policy is a security policy. The same protocol, same domain name, same port. To ensure security, only interfaces under the same domain name are allowed to interact with each other. Client scripts from different sources cannot read or write resources from each other without authorization.
- The same origin policy limits the following items:
-
Cookie, LocalStorage,IndexedDB, etc.
-
DOM node
-
After an AJAX request is sent, the browser intercepts the non-same-origin request. But there are three tags that allow cross-domain loading of resources:
<img src=XXX> <link href=XXX> <script src=XXX> Copy the code
So that’s where JSONP comes in.
2. Common cross-domain scenarios
If any of the fields of protocol, subdomain name, main domain name, or port number are different, they are counted as different sources.
Note: Two points in particular:
- First: the “front end” can’t do anything about cross-domain problems caused by protocols and ports.
- Second: in cross-domain problems, it is only identified by the “head of the URL” rather than whether the corresponding IP address of the domain name is the same. The header of the URL reads “Protocol, domain name and port must match”.
- Third: The request is cross-domain, so is it sent at all? Cross-domain does not mean that the request cannot be sent out, the request can be sent out, the server can receive the request and return the result normally, but the result is blocked by the browser
Two. Cross-domain solutions
1. JSONP
1.1 the json principle
Web pages can get JSON data dynamically generated from other sources by taking advantage of the <script> tag's lack of cross-domain limitations. JSONP requests must be supported by the other party's server.Copy the code
1.2 Comparison between JSONP and AJAX Similar to AJAX, JSONP is a way for a client to send a request to a server and obtain data from the server. But AJAX is a same-origin policy,JSONP is a non-same-origin policy (cross-domain request)
1.3 Advantages and Disadvantages Of JSONP JSONP is simple and compatible, and can be used to solve the problem of cross-domain data access in mainstream browsers. The disadvantages are that supporting only get methods is limited and insecure and may be subject to XSS attacks.
1.4 Implementation process of JSONP
- Declare a callback function whose name (such as show) is passed to the server that requests data across domains and whose parameter is to fetch the target data (the data returned by the server).
- Create a
- Once the server receives the request, it needs to do something special: concatenate the name of the function passed in with the data it needs to give you into a string, for example: the name of the function passed in is show, and the data it prepares is show(‘ I don’t love you ‘).
- Finally, the server returns the data to the client through HTTP protocol, and the client calls the callback function (show) previously declared to operate on the returned data.
Now let’s wrap a JSONP function ourselves
Function JSONP ({url, params, callback}) {return new Promise((resolve, resolve) reject) => { let script = document.createElement('script'); params = JSON.parse(JSON.stringify(params)); let arrs = []; for (let key in params) { arrs.push(`${key}=${params[key]}`); } arrs.push(`callback=${callback}`); script.src = `${url}? ${arrs.join('&')}`; document.body.appendChild(script); window[callback] = function (data) { resolve(data); document.body.removeChild(script); }})} / / front end call json ({url: 'http://localhost:3000/say', params: {wd: 'I Love you'}, the callback: 'show'}). Then (data => {console.log(data)}) var router = express.Router(); var app = express(); Router. Get ('/say',function(req,res,next) {let data = {username: 'zs', password: 123456 } let {wd , callback} = req.query; console.log(wd); console.log(callback); / / the callback function is invoked, and respond to res. The end (` ${callback} (${JSON. Stringify (data)}) `); }) app.use(router); app.listen(3000);Copy the code
2. CORS
CORS requires both browser and backend support. IE8 and IE9 need to use XDomainRequest to realize that the browser will automatically carry out CORS communication. The key to realize CORS communication is the back end. As long as the backend implements CORS, it implements cross-domain. To enable CORS, set access-Control-allow-Origin on the server. This attribute indicates which domain names can access resources. If a wildcard is set, all websites can access resources. Although setting up CORS has nothing to do with the front end, solving cross-domain problems in this way can result in two cases of simple and complex requests being sent.
A simple request
As long as the following two conditions are met, it is a simple request
Condition 1: Use one of the following methods:
- GET
- HEAD
- POST
Condition 2: The value of the content-Type is limited to one of the following:
- text/plain
- multipart/form-data
- Any XMLHttpRequestUpload object in the Application/X-www-form-urlencoded request does not register any event listeners;
Complex request
A request that does not meet these criteria is definitely a complex request. A CORS request for a complex request will add an HTTP query before formal communication, called a “precheck” request. This request is the option method, through which to know whether the server allows cross-domain requests. When a PUT request is sent to the background, it is a complex request and the background needs to be configured as follows:
Res.setheader (' access-control-allow-methods ', 'PUT') res.setheader (' access-control-max-age ', If (req.method === 'OPTIONS') {res.end()} app.put('/getData', function(req, Res) {console.log(req.headers) res.end(' I don't love you ')})Copy the code
Let’s look at an example of a complete request and look at the fields associated with a CORS request
<script> let XHR = new XMLHttpRequest(); document.cookie = 'name=hw'; xhr.withCredentials = true; / / the front set whether or not to bring a cookie XHR. Open (' PUT ', 'http://localhost:4000/getData', true); xhr.setRequestHeader('name','hw'); xhr.onreadystatechange = function() { if(xhr.readyState === 4) { if(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) { console.log(JSON.parse(xhr.response)); console.log(xhr.getResponseHeader('name')) } } } xhr.send(); </script> // server1.js let express = require('express'); let app = express(); App.use (express.static(__dirname)) app.listen(3000) // let express = require('express') let app = express() let WhitList = ['http://localhost:3000'] // Set whitelist app.use(function(req, res, Next) {let origin = req.headers. Origin if (whitlist.includes (origin)) {// Set which source can access me Res. setHeader(' access-Control-allow-headers ', Origin) Res.setheader (' access-control-allow-methods ', 'PUT') // Cookie res.setHeader(' access-Control-allow-credentials ', Res.setheader (' access-Control-max-age ', 6) res.setheader (' access-Control-expose-headers ', 6) res.setheader (' access-Control-expose ', 6) 'name') if (req.method === 'OPTIONS') {res.end()}} next()}) app.put('/getData', function(req, res) { let data = { username : 'zs', password : 123456} console.log(req.headers) res.setheader ('name', 'jw') Res.end (json.stringify (data))}) app.get('/getData', function(req, res) { console.log(req.headers) res.end('he') }) app.listen(4000)Copy the code
3. postMessage
PostMessage is an API in HTML5 XMLHttRequest Level 2, and is one of the few window properties that operate across domains. It can be used to solve the following problems:
- Data transfer between the page and the new window it opens
- Messaging between multiple Windows
- Page with nested IFrame message delivery
- Cross-domain data transfer for the three scenarios above
The postMessage() method allows scripts from different sources to communicate asynchronously in a limited manner, enabling cross-text file, multi-window, cross-domain messaging
The API looks something like this: otherWindow.postMessage(message,targetOrigin,[Transfer])Copy the code
- Message: Data to be sent to another window
- TargetOrigin: Specifies which Windows can receive message events via the origin property of the window, which can be the string “*”(unrestricted). Or a URL. If the protocol of the target window, host address, or port does not match the value provided by targetOrigin, the message will not be sent. A message will only be sent if all three match.
- Transfer (Optional): A string of Transferable objects that are transferred at the same time as Message. Ownership of these objects is transferred to the receiver of the message, and ownership is no longer retained by the sender.
Let’s use an example to illustrate any use
4. websocket
The WebSocket protocol is essentially a TCP-based protocol. In order to establish a WebSocket connection, the client browser first sends an HTTP request to the server. This request differs from the usual HTTP request and contains some additional headers. “Upgrade:WebSocket” indicates that this is an HTTP request for a protocol Upgrade. The server parses these additional headers and generates a reply message back to the client. The WebSocket connection between the client and the server is established. The two parties can communicate freely through the connection channel, and the connection persists until either the client or the server actively closes the connection.
The native WebSocket API is not easy to use, so we use socket. IO, which nicely encapsulates the WebSocket interface, provides a simpler, flexible interface, and provides backward compatibility for browsers that do not support WebSocket. Let’s look at another example:
Let Data = {username: 'hw', password: 456789 } let socket = new WebSocket('ws://localhost:4000'); socket.onopen = function() { socket.send(JSON.stringify(Data)); } socket.onMessage = function(e) {console.log(json.parse (e.ata)); </script> // let express = require('express'); let app = express(); let WebSocket = require('ws'); Let WSS =new websocket. Server({port:4000}) // define Data let Data = {username: 'zs', password: 123456 } wss.on('connection', function(ws) { ws.on('message',function(data) { console.log(JSON.parse(data)) ws.send(JSON.stringify(Data)) }) })Copy the code
5. Node middleware proxy (cross domain twice)
Implementation principle: ** The same origin policy is a standard that the browser must follow, but the same origin policy is not required if the server requests the server. ** Proxy server, need to do the following steps:
- Accept client requests
- Forwards the request to the server
- Get the server response data
- The response is forwarded to the client
Let’s look at another example:
<script> function ajax({url = '', method = 'get', headers = {}, Data = ''}) {return new Promise((resolve,reject) => {var XHR = new XMLHttpRequest(); xhr.onreadystatechange = function() { if(xhr.readyState === 4) { if((xhr.status >= 200 && xhr.status < 300) || Xhr.status === 304) {try {var response = json.parse (xhr.responseText); resolve(response); } catch( e ) { reject(e); } } else { reject(new Error('Request was unsuccessful' + xhr.statusText)); } } } xhr.open(method,url,true); For (let key in headers) {xhr.setrequestheader (key,headers[key]); } xhr.send(JSON.stringify(data)) }) } ajax({ url : 'http://localhost:3000', method : 'post', headers : { 'Content-Type':'application/json; charset=utf-8' }, data : { username : 'hw', password : '789' } }) .then((value,code)=>{ console.log(value) }) .catch(err=>{ console.log(err) }) </script> // Proxy server (http://localhost:3000) const HTTP = require(' HTTP '); // Step 1: Const server = http.createserver ((request, WriteHead (200, {' access-Control-allow-origin ': access-Control-allow-origin: access-Control-allow-origin: access-Control-allow-origin: access-Control-allow-origin: access-Control-allow-origin: access-Control-allow-origin: '*', 'Access-Control-Allow-Methods': '*', 'Access-Control-Allow-Headers': 'Content-Type' }) if(request.method === 'options') { response.end(); } // Step 2: forward the request to the server const proxyRequest = http. request({host: '127.0.0.1', port: 4000, url: '/', method: request.method, headers: Request. Headers,}, serverResponse => {// Var body = 'serverResponse.on('data', chunk => {body += chunk}) serverResponse.on('end', () => {console.log('The data is' + body) Forward the response to the browser response.end(body)})}).end()}) server.listen(3000, ()=>{console.log('The proxyServer is running at http://localhost:3000')}) // Backend server // http://localhost:4000 const HTTP = require('http'); const data = { title : 'zs', password : '123'}; const server = http.createServer((request,response) => { if(request.url === '/') { response.end(JSON.stringify(data)) } }) server.listen(4000,'127.0.0.1',()=> {console.log('The server is running at http://127.0.0.1:4000')})Copy the code
Nginx reverse proxy
preface
To be honest,nginx takes a bit of time to get familiar with, so I’m going to introduce how to use nginx to cross domains
Nginx and node. Js
'Nginx is a lightweight HTTP server with an event-driven asynchronous non-blocking processing framework that provides excellent IO performance and is often used for server-side reverse proxies and load balancing. 'Copy the code
This may seem similar to Node.js, but they both have their own areas of expertise :Nginx is better at handling low-level server resources (static resources handling forwarding, reverse proxies, load balancing, etc.), while Node.js is better at handling upper-level specific business logic. The two can be combined to help front-end development.
Proxy server
What is a reverse proxy? Internet applications are based on the BASIC CS architecture, namely the client side and the server side. Proxy is actually a layer between the client and the real server to provide specific services of the server, that is, the proxy server.
Forward agent
The forward proxy is something you’ve all used before. In fact, the wall scaling tool is a forward proxy tool. It will proxy the web page request from the browser to the outside-wall server to a proxy server that can access the website. The proxy server proxy obtains the web page content from the outside-wall server and forwards it to the client. The specific process is as follows:
The reverse proxy
Reverse proxy is the opposite of forward proxy.
In a reverse proxy (in fact, this happens to page requests on all large web sites), a client sends a request that wants to access content on a server server. Instead, it will be sent to a proxy server, which will proxy requests to internal servers on the same LAN as the user, where the content that the user really wants is stored. In other words, a unified proxy entry is provided for external clients. All requests of clients go through the proxy server first, and the proxy controls which server content is really accessed on the Intranet. The proxy server and the real server can be directly accessed and belong to the same LAN(server Intranet). The agent is transparent to the user, that is, unaware.
Why nginx reverse proxy
The reason:
- Security and permissions. As you can see, with a reverse proxy, the client will not be able to access the real content server directly through requests, but must go through Nginx first. The server can be secured by filtering dangerous or unauthorized requests at the Nginx layer.
- Load balancing. Such as the contents of a website is deployed in a number of servers, you can think of these machines as a cluster, then nginx receives the client requests can be “evenly” assigned to the all servers in the cluster (internal module provides a variety of load balancing algorithm), so as to realize the load balance of the server pressure. In addition, nginx with health check function (server heartbeat check), regularly polling to send health inspection request all the server in the cluster, to check for the server in the cluster in the abnormal state, once found that a server is unusual, so in the future the agent in the client request will not be sent to the server (to the back of the health check Now the server is back to normal) to ensure the stability of client access.
Download and install nginx in Windows
Nginx downloads the nginx configuration
A bit of nginx functionality
1. Quickly implement simple access control
It is common to encounter a desire to make certain groups of users accessible, such as the corporate Intranet, or to block access to a URL.
The nginx configuration is as follows: location / {deny 192.168.1.100; // allow 192.168.1.10/200; // allow 10.110.50.16; deny all; // Disable all}Copy the code
Deny and allow are syntax in ngx_HTTP_access_module (built-in). Use from top to bottom matching, matching to jump out no longer continue to match. For example, the above configuration means that 192.168.1.100 is disabled first, then access is allowed in the IP segment 192.168.1.10-200 (excluding 192.168.1.100), and IP 10.110.50.16 is allowed separately The remaining unmatched access is prohibited.
2. Cross-domain solutions
In many ways to solve the cross domain, it is inevitable to need the support of the server, using Nginx can be pure front-end to solve the request cross domain problem. Nginx configuration is as follows:
server { listen 3002; server_name localhost; location /ok { proxy_pass http://localhost:3000; Add_header access-control-allow-methods *; Add_header access-control-max-age 3600; add_header access-control-max-age 3600 Add_header access-control-allow-credentials true; Add_header access-Control-allow-origin is not supported for cookie requests $http_origin; Add_header access-control-allow-headers $http_access_control_request_headers; If ($request_method = OPTIONS){return $request_method; }}}Copy the code
The resources
Nine ways to implement cross-domain request nGINx and front-end development
conclusion
- CORS supports all types of HTTP requests and is the fundamental solution to cross-domain HTTP requests.
- JSONP supports only GET requests. The advantage of JSONP is that it supports older browsers and can request data from sites that do not support CORS
- Both the Node middleware proxy and the Nginx reverse proxy have no restrictions on the server through the same origin policy
- In daily work, the most commonly used cross-domain solutions are CORS and NGINX reverse proxies
The last
Okay, I’ll admit that I paddled with nginx at the end.
This, Nginx has been learning me for days and I haven’t figured it out yet.
Well, I’ll fill it in later.