The Internet says a lot, but after watching it is still very confused, so I myself to summarize.
There are 8 ways to solve JS cross-domain problems:
- Jsonp (GET only)
- The reverse proxy
- CORS
- Document.domain + iframe cross domain
- Window. name + iframe cross domain
- window.postMessage
- location.hash + iframe
- web sockets
Each method has its own advantages and disadvantages, but the front-end development is more commonly used jSONP, reverse proxy, CORS:
- CORS stands for Cross-Origin Resource Sharing. It is a W3C standard and a fundamental solution for cross-source AJAX requests.
- The advantages are: orthodox, up to standard,
- Disadvantage is: the need for server side coordination, more trouble.
- At the heart of JSONP is dynamic addition
<script>
Tag to invoke the js script provided by the server.- Advantages: good support for older browsers,
- Disadvantage 1: Only GET requests are supported.
- Disadvantage 2: Security issues (there may be security issues in the request code).
- Disadvantage 3: It is not easy to determine if a JSONP request has failed.
- Reverse proxies are compatible with the above determinations, but are used only in front-end development mode and rarely in live environments.
- This is required only when the domain name in the development environment is different from that in the online environment.
- If the online environment is too complex, using reverse proxies to implement cross-domain will become cumbersome, then jSONP or CORS will be used to handle this.
These three methods are mainly described here. Other methods are not specified.
1. What are cross-domain issues
Cross-domain issues typically occur only when web requests are made using javascript in front-end development and the browser restricts secure access to web request data.
The error is as follows:
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://XXXXXX' is therefore not allowed access.
Copy the code
Ii. Why cross-domain problems occur
Because browsers are restricted by the same-origin policy, js of the current domain name can only read window properties in the same domain.
In other words, crossing the browser’s same-origin policy limits triggers what we call a “cross-domain” problem.
2.1 What is the Same-origin Policy
Homology means that three sources are the same at the same time:
- The agreement is the same
- Domain name is the same
- The same port
For example, http://www.example.com/dir/page.html,
The protocol is HTTP://The domain name is www.example.com. The port is80
// Its homology is as follows:
http:/ / www.example.com/dir2/other.html:
http:/ / example.com/dir/other.html: different source (domain name)
http:/ / v2.www.example.com/dir/other.html: different source (domain name)
http:/ / www.example.com:81/dir/other.html: different source (port)
Copy the code
In general, as long as all three are not identical at the same time, they are not homologous, and the same-origin policy restriction is triggered.
2.2 What does the Same-origin Policy Limit
Limit:
- Cookie, LocalStorage, and IndexDB cannot be read
- DOM and JS objects cannot be retrieved
- The Ajax request could not be sent
This is what we call a “cross-domain problem”.
Detailed the same-origin policy related, you can refer to www.ruanyifeng.com/blog/2016/0…
Third, addressing cross-domain issues
3.1 Using reverse Proxy
3.1.1 What is a Reverse proxy?
The difference between reverse proxy and forward proxy:
- Forward Proxy, commonly referred to as Proxy, means that when users cannot access external resources normally, for example, they cannot access Twitter due to the influence of GFW, we can bypass the firewall through Proxy to connect users to the target network or service.
- Reverse Proxy refers to a Proxy server that receives Internet connection requests, forwards the requests to the Intranet server, and returns the results to the Internet client. In this case, the Proxy server acts as a server externally.
You can use the principle of reverse proxy, we through an intermediate proxy servers (the reverse proxy server), the client network request some host, domain, rewrite the port and protocol, etc, make its simulation for access to the target server’s request, the modeled as not violating the same-origin policy request to the target server.
3.1.2 How to Use a Reverse proxy Server to Solve cross-domain Problems
- The front-end Ajax requests the local reverse proxy server
- After the local reverse proxy server receives this message:
- Modify http-header information of the request, such as referer, host, and port
- After modification, the request is sent to the actual server
- A real server would process a request as if it were a same-origin (see same-origin policy) request
Front-end development now uses NodeJS as a local reverse proxy server
// Import routes after Express
var app = express();
var apiRoutes = express.Router();
app.use(bodyParser.urlencoded({extended:false}))
// Access the route address of the reverse proxy
apiRoutes.get("/lyric".function (req, res) {
var url = "https://c.y.qq.com/lyric/fcgi-bin/fcg_query_lyric_new.fcg";
// Overwrite the request information on the source side and redirect it to the target server
axios.get(url, {
headers: { / / modify the header
referer: "https://c.y.qq.com/".host: "c.y.qq.com"
},
params: req.query
}).then((response) = > {
var ret = response.data
if (typeof ret === "string") {
var reg = /^\w+\(({[^()]+})\)$/;
var matches = ret.match(reg);
if (matches) {
ret = JSON.parse(matches[1])
}
}
res.json(ret)
}).catch((e) = > {
console.log(e)
})
});
// Use this route
app.use("/api", apiRoutes);
Copy the code
This code is executed as follows:
- Node JS acts as a reverse proxy server, and then uses Express on top of it for routing,
- Add a route map in NodeJS which is responsible for the source-side request, map it to the target server API interface, and rewrite the request in this route to simulate the same origin policy requirements of the target server API interface.
- The source requests the route previously set by the NodeJS reverse proxy server, passing the parameters to it, and then the NodeJS reverse proxy rewrites its request and forwards it to the destination server.
3.2 Using JSONP Mode
3.2.1 What is JSONP
Some JSONP articles are called dynamically creating scripts, because they do dynamically write the contents of script tags to achieve cross-domain effects:
- AJAX cannot cross domains because of the same origin policy, but tags with SRC attributes (for example
<script>, <img>, <iframe>
) is not restricted by this policy, so we can add them dynamically to the page<script>
Tag to access resources across domains, which is at the heart of the JSONP scheme. In other words,The idea is that there is no cross-domain problem when the front-end requests static resources. - JSONP can only be used in get mode.
- JSONP(JSON Padding) is a way of using JSON that allows the user to pass a callback argument to the server. The server then returns the data with the callback argument wrapped around the JSON data as a function name. The client can then customize its own functions to automatically process the returned data.
3.2.1 How to Use JSONP to solve cross-domain problems:
A simpler example:
The indirect introduction of a piece of JS code from the outside through tags that are not subject to the same origin policy, such as script. A GET request is made to the target source via the script tag, and the server returns code containing JS based on the parameters of the request.
Var data = json.parse (obj); var data = json.parse (obj); console.log(data.name); //jiavan console.log(data.age); / / 20} < / script > < script SRC = "http://cv.jiavan.com/test/data.php?callback=getData" > < / script > / code/server <? PHP $func = $_GET['callback']; $data = '{"name": "jiavan", "age": 20}'; echo $func."(".$data.");" ; ? < span style = "box-width: border-box; color: RGB (74, 74, 74); line-height: 22px; font-size: 14px! Important; word-break: inherit! Important;"Copy the code
GetData (‘{“name”: {“name”: {“name”: {“name”: {“name”: {“name”: {“name”: {“name”: {“name”: {“name”: “jiavan”, “age”: 20}’); Even a piece of JS code passes data to a callback function for processing, thus completing cross-domain.
Reference: segmentfault.com/a/119000000…
A more complicated example:
! [](JSONP – Reverse proxy -CORS Personal summary of JS cross-domain Problems (update V2.0) /15166939118513.jpg)
References from segmentfault.com/a/119000001… The figure of
- The client and server agree that a parameter name represents a JSONP request, such as the parameter name callback.
- The server then prepares a javascript file for the previously agreed callback argument with a function name that is the same as the one requested by the client. (See the following example:
ip.js
) - The client then registers a locally run function with the same name as the one that calls the server for the callback. (For example: foo and request time
callback=foo
The names are the same. - Then the client to the server
The way the json
The request. - The server returns the configured JS file (
ip.js
) to the client - The client browser parses the script tag and executes the returned javascript file, at which point the data is passed as arguments to the client’s pre-defined callback function.
- This is equivalent to a local execution that registers function foo, and then gets a function foo that contains the parameters passed in (e.g
foo({XXXXX})
)
- This is equivalent to a local execution that registers function foo, and then gets a function foo that contains the parameters passed in (e.g
Server-side file ip.js
foo({
"ip": "8.8.8.8"
});
Copy the code
Client file jsonp.html
<! DOCTYPE html PUBLIC"- / / / / W3C DTD XHTML 1.0 Transitional / / EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script>
// Dynamically insert script tags into HTML
function addScriptTag(src) {
var script = document.createElement('script');
script.setAttribute("type"."text/javascript");
script.src = src;
document.body.appendChild(script);
}
// Get the jSONp file
window.onload = function () {
addScriptTag('http://example.com/ip?callback=foo');
}
// Execute the local JS logic, which must be consistent with the function obtained from the jsonp file
function foo(data) {
console.log('Your public IP address is: ' + data.ip);
};
</script>
</head>
<body>
</body>
</html>
Copy the code
3.3 CORS way
CORS is a W3C standard, which stands for “Cross-origin Resource Sharing”. It allows browsers to issue XMLHttpRequest requests across source servers, overcoming the limitation that AJAX can only be used in the same source.
- CORS requires both browser and server support. Currently, all browsers support this function, and Internet Explorer cannot be lower than Internet Explorer 10.
- The entire CORS communication process is completed automatically by the browser without user participation. For developers, CORS communication is no different from same-origin AJAX communication, and the code is exactly the same. As soon as the browser discovers that an AJAX request crosses the source, it automatically adds some additional headers, and sometimes an additional request, but the user doesn’t feel it.
Therefore, the key to CORS communication is the server side. As long as the server implements the CORS interface, cross-source communication is possible.
3.3.1 CORS requests fall into two categories
- A simple request
- Non-simple request
As long as the following two conditions are met, it is a simple request.
(1) Request method is one of the following three methods:
- HEAD
- GET
- POST
(2) HTTP headers do not exceed the following fields:
- Accept
- Accept-Language
- Content-Language
- Last-Event-ID
- Content-type: Application/X-www-form-urlencoded, multipart/form-data, text/plain
Any request that does not meet both conditions is a non-simple request.
3.3.2 Processing simple requests
For simple requests, an Origin field is automatically added to the header information to specify the source (protocol + domain name + port) from which the request is sent. Based on this value, the server decides whether to approve the request or not.
GET /cors HTTP/1.1
Origin: http://api.bob.com
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0.Copy the code
If Origin does not specify a licensed source, the server will return a normal HTTP response. The browser realizes that the response header does not contain the Access-Control-Allow-Origin field, and knows that something is wrong, throwing an error that is caught by XMLHttpRequest’s onError callback. Note that this error cannot be identified by the status code, because the status code for the HTTP response might be 200.
Access-control-allow-origin = access-Control-allow-origin = access-Control-allow-origin = access-Control-allow-origin
Access-Control-Allow-Origin: http://api.bob.com
Content-Type: text/html; charset=utf- 8 -
Copy the code
3.3.3 Non-simple Requests
For non-simple requests, an HTTP query request is added before formal communication, called a “preflight” request.
The browser asks the server if the domain name of the current web page is on the server’s license list, and what HTTP verb and header fields can be used. The browser issues a formal XMLHttpRequest request only if it receives a positive response; otherwise, an error is reported.
Note that there are two requests sent, the first is a pre-check request, and the second is the actual request!
First issue precheck request:
// Precheck the 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
In addition to the Origin field, the precheck request header contains two special fields.
(1) Access – Control – Request – Method
This field is required to list which HTTP methods are used by the browser for CORS requests, in this example PUT.
(2) Access – Control – Request – Headers
This field is a comma-separated string that specifies the additional Header field to be sent by a browser CORS request, x-custom-header in the example above.
Then the server receives the precheck request:
Verify that cross-source requests are allowed after checking the Origin, Access-Control-request-Method, and access-Control-request-HEADERS fields.
// Precheck the response to the request
HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2.061. (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
Finally, once the server has passed the precheck request:
In the future, every normal BROWSER CORS request will have an Origin header field, just like a simple request. The server also responds with an Access-Control-Allow-Origin header field.
// After the request, like a pass, there is no need to do a pre-check request.
PUT /cors HTTP/1.1
Origin: http://api.bob.com
Host: api.alice.com
X-Custom-Header: value
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0.Copy the code
Details refer to the www.ruanyifeng.com/blog/2016/0 here…
In general, there are only 2 places you need to know, and the rest can be followed by analogy:
- CORS needs one on the server side
Access-Control-XXX
In order to handle the source identification of the request. - CORS adds an OPTIONS request for non-simple requests.
Reference Documents:
- Eight front-end solutions to cross-domain problems
- Browser same origin policy and its circumvention method
- Tonghuashuo. Making. IO/blog/json….
- www.cnblogs.com/yuzhongwusa…
- www.cnblogs.com/dowinning/a…
- Segmentfault.com/a/119000000…