This is the 31st day of my participation in Gwen Challenge. For details, see Gwen Challenge.
Cross-domain request is a common problem in front-end development. Usually, in order to improve the development efficiency, the front and back ends are separated and deployed independently during the project development process, which may lead to inconsistent domain names of the front and back ends and cross-domain problems in the communication process. Because the project development process involves, take this opportunity to sort out cross-domain problems, is also a common problem in front-end interview.
Why is there a cross-domain problem?
The problem is that with the rise of AJAX, Web applications are increasingly demanding cross-domain access, and AJAX is constrained by browser security when making cross-domain requests.
To ensure security, browsers introduce the same origin policy. This strategy restricts the access of resources by Javascript executing on the page. For example, Javascript cannot directly access the DOM structure of the page under different sources, and the server response cannot be obtained when sending requests to different sources (the server will normally process the request and return the response content, But the returned content is blocked by the browser).
What is the same origin policy?
SOP (Same Origin Policy) is a convention introduced by Netscape in 1995. SOP is the core and most basic security function of the browser. Without the Same Origin policy, the browser is vulnerable to XSS and CSFR attacks. Same-origin means that the protocol, domain name, and port are the same. Even if two different domain names point to the same IP address, they are not same-origin.
The same origin policy restricts the following behaviors:
Cookie
,LocalStorage
和IndexDB
Unable to readDOM
和Javascript
Object not availableAJAX
Request receive limit
What is cross-domain
URL | instructions | Whether to allow communication |
---|---|---|
http://www.devpoint.cn/name1.js 、http://www.devpoint.cn/name2.js |
Different paths for the same domain name | allow |
http://www.devpoint.cn:8080 、 http://www.devpoint.cn |
Different ports for the same domain name | Don’t allow |
http://www.devpoint.cn 、http://crayon.devpoint.cn |
The primary domain is the same, but the subdomain is different | Don’t allow |
http://www.devpoint.cn 、 http://www.aliyun.com |
Primary domain different | Don’t allow |
http://www.devpoint.cn 、 https://www.devpoint.cn |
Agreement is different | Don’t allow |
The solution
jsonp
In order to reduce the load of the Web server, static resources such as JS, CSS and IMG are separated to another server with an independent domain name, and static resources are loaded from different domain names through corresponding tags in the HTML page. This is allowed by the browser. Based on this principle, script can be dynamically created. Request a reference url to achieve cross-domain communication.
Limitations: Only GET requests
HTML code:
<script type="text/javascript"> function onLogin(res){ console.log(res); } < / script > / / reference file < script type = "text/javascript" SRC = "https://www.devpoint.cn/login?user=devpoint&callback=onLogin" > / / AJAX, With jquery. Js < script type = "text/javascript" > $. Ajax ({url: "https://www.devpoint.cn/login", type: "get", dataType: "json", JsonpCallback :"onLogin", // custom callback data:{}}); </script>Copy the code
Server-side code (PHP) :
echo "onLogin({"result":"success", "user": "devpoint"})"
Copy the code
document.domain
+ iframe
Implementation principle: Two pages are forced to set as the same primary domain through Javascript document.domain to achieve the effect of co-domain, that is, the pages in iframe are communication proxy pages, proxy pages must be deployed in the same site with the back-end server.
Limitations: Only cross domains with the same primary domain name and different subdomains.
Home page: (assuming the access path is: https://blog.devpoint.cn/login.html), the code is as follows:
<iframe id="proxyIframe" src="https://api.devpoint.cn/proxy.html"></iframe>
<script type="text/javascript">
document.domain = "devpoint.cn";
const user = "devpoint";
const elemIframe = document.getElementById("proxyIframe");
elemIframe.login(user,function(res){
console.log(res);
});
</script>
Copy the code
Agent page: https://api.devpoint.cn/proxy.html, the code is as follows:
<script type="text/javascript"> document.domain = "devpoint.cn"; } function login(user,callback){ajax(data,callback); } </script>Copy the code
location.hash
+ iframe
Implementation principle: A wants to communicate with B across domains through the middle page C.
Limitations: Cumbersome, and the length of the value passed by location.hash is limited
Three pages, different fields use iframe location.hash to transfer values, the same fields directly js access to communicate.
A domain: A.html -> B domain: B.html -> A domain: C.HTML, A and B different domains through hash value one-way communication, B and C are also different domains can only one-way communication, but C and A are the same domain, so C can access all objects on A page through parent. Parent.
A.h HTML code (http://www.devpoint.cn/a.html) as follows:
<iframe id="iframe" src="http://www.crayon.dev/b.html" style="display:none;" ></iframe> <script type="text/javascript"> var iframe = document.getElementById("iframe"); SetTimeout (function() {ifame. SRC = ifame. SRC + "#user=devpoint"; }, 1000); Function onCallback(res) {alert("data from c.html --> "+ res); } </script>Copy the code
B.h HTML code (http://www.crayon.dev/b.html) as follows:
<iframe id="iframe" src="http://www.devpoint.cn/c.html" style="display:none;" ></iframe> <script type="text/javascript"> var iframe = document.getElementById("iframe"); Onhashchange = function () {ifame. SRC = ifame. SRC + location.hash; }; </script>Copy the code
C. the TML (http://www.devpoint.cn/c.html) code is as follows:
<script type="text/javascript"> // Listen for hash values window.onhashchange = function () { The results back to the window. The parent. The parent. OnCallback (" hello, "+ location. Hash. Replace (" # user =", "")); }; </script>Copy the code
postMessage
PostMessage is an API in HTML5 XMLHttpRequest Level 2, and is one of the few window properties that can 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
- Pages with nested
iframe
Messaging, including offline files (HTML packaged with APP and installed on local pages) - Cross-domain data transfer for the three scenarios above
The postMessage(data, Origin) method takes two arguments:
data
The HTML5 specification supports any primitive type or copiable object, but some browsers only support strings, so it’s best to use them when passing argumentsJSON.stringify()
Serialization.origin
: Protocol + host + port number. The value can also be “*”, which indicates that the port can be sent to any window. If you want to specify the same source as the current window, set this parameter to “*”/
。
CORS
Common cross-domain request: Access-Control-allow-Origin can be set on the server, and the front-end does not need to be set.
Cross-domain requests require cookies: both the front and back ends need to be set.
Note that due to the restriction of the same-origin policy, the cookie read is the cookie of the domain where the cross-domain request interface resides, not the current page.
Currently, all browsers support this feature, and CORS has become a mainstream cross-domain solution. Cross-domain requests for the DEBUG functionality in a project use this scheme.
Front-end Settings: The withCredentials attribute needs to be set in the request header
headers: {
"x-fdn-sign": apiSign,
withCredentials: "true"
}
Copy the code
Server Settings
response.setHeader("Access-Control-Allow-Origin", "*"); Responsetheader (" access-Control-allow-credentials ", "true"); response.setHeader(" access-Control-allow-credentials ", "true");Copy the code
conclusion
Although modern front-end development rarely touches on cross-domain issues, it is mostly through framework or scaffolding agents, or NGINX agents, etc. But it’s worth knowing as a basis.