Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to realize the cross-domain front and back end of JS

2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/01 Report--

This article mainly introduces the relevant knowledge of "how to achieve JS cross-domain front and back end". The editor shows you the operation process through an actual case. The operation method is simple, fast and practical. I hope this article "how to achieve JS cross-domain front and back end" can help you solve the problem.

Homologous security policy for browsers

Homologous policy, which is a famous security policy proposed by Netscape. All browsers that support JavaScript now use this strategy. The so-called homology means that the domain name, protocol and port are the same. The same origin policy is the behavior of the browser, which is to protect the local data from being contaminated by the data obtained by the JavaScript code, so it intercepts the data received from the request sent by the client, that is, the request is sent and the server responds, but cannot be received by the browser.

Homology: protocol + domain name + port. So, what is cross-domain?

What is cross-domain?

It is simply understood that due to the restriction of the same origin policy of JavaScript, the js under the a.com domain name cannot manipulate the objects under the b.com or c.a.com domain name. A more detailed description can be found in the following table:

URL indicates whether to allow communication http://www.a.com/a.js

Http://www.a.com/b.js allows http://www.a.com/lab/a.js under the same domain name

Http://www.a.com/script/b.js allows http://www.a.com:8000/a.js in different folders under the same domain name

Http://www.a.com/a.js is not allowed on different ports for the same domain name of http://www.a.com/b.js.

Https://www.a.com/b.js has the same domain name, but different protocols do not allow http://www.a.com/a.js.

Http://70.32.92.74/b.js domain name and domain name corresponding to ip do not allow http://www.a.com/a.js

Http://www.a.com/a.js is not allowed for different subdomains while the primary domain of http://script.a.com/b.js is the same

Http://a.com/b.js same domain name, different second-level domain names (same as above) are not allowed (cookie is also not allowed to access) / / www.yisu.com/a.js

Http://www.a.com/b.js different domain names are not allowed to pay special attention to two points:

First, the "foreground" is powerless if it is the cross-domain problems caused by protocols and ports.

Second: in the cross-domain problem, the domain is only identified by the "head of URL" rather than trying to determine whether the same ip address corresponds to two domains or whether the two domains are on the same ip.

"the first part of URL" means _ window.location.protocol + _ window.location.host, which can also be understood as "Domains, protocols and ports must match".

Front-end cross-domain solution (JavaScript)

Next, let's briefly summarize the general ways to deal with cross-domain in the "foreground".

1. Setting of document.domain+iframe

Examples where the primary domain is the same but the subdomain is different can be solved by setting up document.domain. The specific approach is to add document.domain = 'a.compose to the http://www.a.com/a.html and http://script.a.com/b.html files respectively, and then create an iframe in the a.html file to control the contentDocument of the iframe, so that the two js files can "interact". Of course, this method can only solve the situation where the primary domain is the same but the secondary domain name is different. If you whimsically set the domian of script.a.com to alibaba.com, it will obviously be misreported! The code is as follows:

A.html on www.a.com

Document.domain ='a. Composter. Ifr = document.createElement ('iframe'); ifr.src =' http://script.a.com/b.html';ifr.style.display = 'none';document.body.appendChild (ifr); ifr.onload = function () {var doc = ifr.contentDocument | | ifr.contentWindow.document; / / manipulate b.html alert here (doc.getElementsByTagName ("H2") [0] .childNodes [0] .nodeValue);}

B.html on script.a.com

Document.domain = 'a.com'

This method is suitable for any page in {www.jb51.com, jb51.com, script.jb51.com, css.jb51.com} to communicate with each other.

Note: the domain of a page is equal to _ window.location.hostname by default. The primary domain name is a domain name without www, such as a.com. The primary domain name is usually preceded by a secondary domain name or a multi-level domain name. For example, www.a.com is actually a secondary domain name. Domain can only be set as the primary domain name, and domain cannot be set to c.a.com in b.a.com.

Question:

1. Security. When one site (b.a.com) is attacked, another site (c.a.com) will cause security vulnerabilities.

2. If you introduce multiple iframe into a page, if you want to be able to operate all iframe, you must set the same domain.

2. Create script dynamically

Although the browser forbids cross-domain access by default, it does not prohibit referencing JS files from other domains in the page, and is free to execute the function in the introduced JS file (including manipulating cookie, Dom, and so on). According to this, complete cross-domain communication can be easily achieved by creating script nodes.

It's interesting to judge that the script node is loaded here: ie can only pass through the readystatechange property of script, and other browsers are the load event of script. Here is a partial way to determine that the script has been loaded.

Js.onload = js.onreadystatechange = function () {if (! this.readyState | | this.readyState = = 'loaded' | | this.readyState = =' complete') {/ / callback execute js.onload = js.onreadystatechange = null;}} here; 3. Use iframe and location.hash

This method is relatively roundabout, but it can solve the problem of footstep replacement in the case of complete cross-domain. The principle is to use location.hash to pass values. The'# helloworld' in url: http://a.com#helloword is location.hash, and changing the hash will not cause the page to refresh, so you can use the hash value for data transfer, of course, the data capacity is limited. Suppose the file cs1.html under the domain name a.com wants to transmit information to the cs2.html under the jb51.net domain. Cs1.html first creates a src that automatically creates a hidden iframe,iframe to point to the cs2.html page under the jb51.net domain. In this case, the hash value can be used to pass parameters. After cs2.html responds to the request, the data will be transferred by modifying the hash value of cs1.html (since the two pages are not in the same domain, IE and Chrome are not allowed to modify the value of parent.location.hash, so you can modify it with the help of an agent iframe;Firefox under the a.com domain name). At the same time, add a timer to the cs1.html to determine whether the value of the location.hash has changed or not, and get the hash value if there is a change. The code is as follows:

First, the files under a.com, cs1.html files:

Function startRequest () {var ifr = document.createElement ('iframe'); ifr.style.display =' none'; ifr.src ='/ / www.yisu.com/lab/cscript/cs2.html#paramdo'; document.body.appendChild (ifr);} function checkHash () {try {var data = location.hash? Location.hash.substring (1):'; if (console.log) {console.log ('Now the data is' + data);}} catch (e) {};} setInterval (checkHash, 2000)

Cs2.html under the jb51.net domain name:

/ / simulate a simple parameter handling operation switch (location.hash) {case'# paramdo': callBack (); break; case'# paramset': / / do something... Break;} function callBack () {try {parent.location.hash = 'somedata';} catch (e) {/ / ie, chrome's security mechanism cannot modify parent.location.hash, / / so use a proxy under an intermediate cnblogs domain iframe var ifrproxy = document.createElement (' iframe'); ifrproxy.style.display = 'none' Ifrproxy.src = 'http://a.com/test/cscript/cs3.html#somedata'; / / Note that the file is document.body.appendChild (ifrproxy) in the "a.com" field;}}

Domain name cs3.html under a.com

/ / because parent.parent and itself belong to the same domain, you can change the value of its location.hash parent.parent.location.hash = self.location.hash.substring (1)

Of course, this also has many disadvantages, such as the data is directly exposed in url, the data capacity and type are limited, and so on.

4. Cross-domain data transmission realized by window.name.

The long list of articles is not easy to read here. For more information, please see the cross-domain data transfer implemented by window.name.

5. Use HTML5 postMessage

One of the coolest new features in HTML5 is the transfer of Cross Document Messaging across document messages. The next generation of browsers will support this feature: Chrome 2.0 +, Internet Explorer 8.0, Firefox 3.0, Opera 9.6, and Safari 4.0 +. Facebook has used this feature to support real-time web-based messaging with postMessage.

OtherWindow.postMessage (message, targetOrigin)

OtherWindow: a reference to the window that receives the information page. It can be the contentWindow property of iframe in the page, the return value of window.open, and the value obtained from window.frames through name or subscript.

Message: the data to be sent, the string type.

TargetOrigin: used to restrict otherWindow. "*" means no restriction.

The code in a.com/index.html:

_ window.onload = function () {var ifr = document.getElementById ('ifr'); var targetOrigin =' http://b.com'; / / if it is written as' http://b.com/c/proxy.html' effect / / if it is written as' http://c.com', it will not postMessage ifr.contentWindow.postMessage ('I was there trees, targetOrigin);}

The code in b.com/index.html:

Window.addEventListener ('message', function (event) {/ / determine the message source address if by the origin attribute (event.origin = =' http://a.com') {alert (event.data); / / pop-up "I was there!" Alert (event.source); / / A reference to window objects in a.com and index.html / / but due to the same origin policy, event.source cannot access window objects}}, false); second, background cross-domain solution

CORS

This is the W3C standard, the full name is "cross-domain resource sharing" (Cross-origin resource sharing).

/ / specify that other domain names are allowed to access' Access-Control-Allow-Origin: http://172.20.0.206'// general usage (, specify domain, dynamic setting), 3 because authentication headers are not allowed and whether cookies// allows subsequent requests to carry authentication information (cookies). This value must be true, otherwise 'Access-Control-Allow-Credentials:true'' is not returned.

The Access-Control-Allow-Origin mentioned in the first line above can be set up in several ways:

Setting up is the simplest and roughest, but the server certainly won't do it for security reasons, and, if so, the browser will not send cookies, even if your XHR has withCredentials set.

A specified domain, such as the http://172.20.0.206 in the figure above, usually has a nginx in the middle of the system, so this is recommended.

Dynamically set to the request domain, when multiple people cooperate, multiple front ends are connected to a background, which is very convenient.

Response supports cross-domain

As you can see from the output of the console above, the reason for the error is that there is no "Access-Control-Allow-Origin" in the header of the requested resource (interface), so we can add it. Where can I add it? Since it is said that there are no requested resources, it is, of course, added to the requested resources, that is, the server.

@ SpringBootApplication@Configuration@RestControllerpublic class ApplicationA {public static void main (String [] args) {SpringApplication.run (ApplicationA.class, args);} @ RequestMapping ("/ test") public Object test (HttpServletRequest request, HttpServletResponse response) {/ / Cross-domain support response.setHeader ("Access-Control-Allow-Origin", "*"); response.setHeader ("Access-Control-Allow-Methods", "POST,GET,PUT,DELETE") Response.setHeader ("Access-Control-Max-Age", "3600"); response.setHeader ("Access-Control-Allow-Headers", "*"); response.setHeader ("Access-Control-Allow-Credentials", "true"); Map map = new HashMap (); map.put ("success", true); map.put ("msg", "I am from the server"); return map }}

Springboot supports cross-domain

The test case is a springboot project that can be done in a simpler way. Override the addCorsMappings method and configure it in the method through a bean that inherits WebMvcConfigurerAdapter.

@ SpringBootApplication@Configuration@RestControllerpublic class ApplicationA extends WebMvcConfigurerAdapter {public static void main (String [] args) {SpringApplication.run (ApplicationA.class, args);} @ RequestMapping ("/ test") public Object test (HttpServletRequest request, HttpServletResponse response) {Map map = new HashMap (); map.put ("success", true); map.put ("msg", "I'm from the server"); return map } / / Cross-domain support @ Override public void addCorsMappings (CorsRegistry registry) {registry.addMapping ("/ * *") .allowedOrigins ("*") .allowCredentials (true) .allowedMethods ("GET", "POST", "DELETE", "PUT") .maxAge (3600);} set multiple Access-Control-Allow-Origin cross-domain access in Java

1. If the server is developed by Java, you can add the following settings to allow cross-domain access, but it is not secure enough to allow all domain names to be accessed.

Response.setHeader ("Access-Control-Allow-Origin", "*")

2. To ensure security, you can add only some domain names to allow access, and you can choose one of the following three locations.

(1) it can be set in the dofilter () method of the filter's filter.

(2) you can set it in the get or post method of servlet.

(3) you can put it on the first line of the jsp page you visit.

3. Using the first method here, pay attention to the web.xml configuration filter (filter).

Public void doFilter (ServletRequest req, ServletResponse res,FilterChain chain) throws IOException, ServletException {/ / convert ServletResponse to HttpServletResponse HttpServletResponse httpResponse = (HttpServletResponse) res / / if it is not port 80, the port needs to be added. If it is a cluster, the address of Nginx is used. Similarly, port String [] allowDomain= {"http://www.baidu.com","http://123.456.789.10","http://123.16.12.23:8080"}; Set allowedOrigins= new HashSet (Arrays.asList (allowDomain)) is added to port 80. String originHeader= ((HttpServletRequest) req) .getHeader ("Origin"); if (allowedOrigins.contains (originHeader)) {httpResponse.setHeader ("Access-Control-Allow-Origin", originHeader); httpResponse.setContentType ("application/json;charset=UTF-8"); httpResponse.setHeader ("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE") HttpResponse.setHeader ("Access-Control-Max-Age", "3600"); httpResponse.setHeader ("Access-Control-Allow-Headers", "Content-Type,Access-Token"); / / if you want to send Cookie to the server, you need to specify the Access-Control-Allow-Credentials field as true httpResponse.setHeader ("Access-Control-Allow-Credentials", "true") HttpResponse.setHeader ("Access-Control-Expose-Headers", "*");} chain.doFilter (req, res);} configure the requested CORS based on nginx

Currently, many requests are not directly exposed, and many do reverse proxies through nginx, so you can use nginx to configure Access-Control-Allow-Origin with fixed requests to achieve cross-domain access. The way is to configure the location proxy on the requested interface and add the header implementation.

# active provider cross-domain configuration location / promotion/activityPro {proxy_pass http://frontHost/promotion/activityPro; add_header 'Access-Control-Allow-Origin'' *'; # add_header 'Access-Control-Allow-Methods'' GET, POST'; # add_header 'Access-Control-Allow-Credentials' "true" # add_header 'Access-Control-Max-Age' 86400; # add_header' Access-Control-Allow-Header' 'Content-Type,*';} 3. Frontend cross-domain JSONP solution

Children's shoes with front-end experience know that sometimes we will directly introduce js, css and other static files of other domain names into our own code. Why are these static files not restricted by browsers? Usually in order to reduce the pressure on the web server, we will separate the static resources such as js and css,img to another server with an independent domain name, separating it from the front end. For this reason, browsers do not restrict cross-domain access to such static resources.

We can dynamically create a script that makes browsers think we want to get static resources, thus giving us a break. The server side also needs to make a change. Instead of returning json directly, it returns a function that executes immediately, and the result of the front-end request is used as an argument to the function.

Back-end API returns

@ SpringBootApplication@Configuration@RestControllerpublic class ApplicationA {public static void main (String [] args) {SpringApplication.run (ApplicationA.class, args);} @ RequestMapping ("/ test") public String test (HttpServletRequest request, HttpServletResponse response, String callback) throws IOException {Map map = new HashMap (); map.put ("success", true); map.put ("msg", "I'm from the server") / / the returned values are as follows: / / callback ({"msg": "I'm from the server", "success": true}); return String.format ("% s (% s);", callback, JsonUtil.toJson (map)) } js natively implements jsonpfunction test () {/ / external domain name. The parameter is the callback function url = "http://localhost:8882/test?callback=_ajax_callback"; / / create a script element var script = document.createElement ('script'); script.type =' text/javascript'; script.src = url; document.head.appendChild (script) after the specified API is returned by the callback agreed with the backend API." } / / API callback function _ ajax_callback (res) {console.log ("callback"); console.log (res);} jQuery implements jsonp$.ajax ({url: 'http://localhost:8882/test', type:' get', dataType: 'jsonp', / / request method jsonpCallback: "_ ajax_callback", / / callback function name data: {}}) Vue.js implements the advantages and disadvantages of jsonpthis.$http.jsonp ('http://localhost:8882/test', {undefinedparams: {}, jsonp:' _ ajax_callback'}) .then ((res) = > {undefinedconsole.log (res);}) JSONP

Advantages: it is not limited by the same origin policy as the Ajax request implemented by the XMLHttpRequest object; it is more compatible and can be run in older browsers without XMLHttpRequest or ActiveX support; and the result can be returned by calling callback after the request is completed.

Disadvantages: it only supports GET requests but does not support other types of HTTP requests such as POST; it only supports cross-domain HTTP requests and cannot solve the problem of how to make JavaScript calls between two pages in different domains.

Other ways to support cross-domain

Nginx reverse proxy: the front end accesses the same domain name, and nginx forwards the request to the external domain name as needed

Back-end proxy: request external resources (such as using HttpClient) in the back-end interface, and then return the result to the front end, so that it is not cross-domain.

Others: cross-domain can also be realized with the help of iframe, postMessage, etc.

Document.domain,window.name,web sockets

This is the end of the introduction on "how to implement the front and back end of JS across domains". Thank you for your reading. If you want to know more about the industry, you can follow the industry information channel. The editor will update different knowledge points for you every day.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report