Home  >  Article  >  Web Front-end  >  Ultra-detailed complete solution to cross-domain problems (with examples)

Ultra-detailed complete solution to cross-domain problems (with examples)

不言
不言forward
2019-01-14 10:05:472527browse

What this article brings to you is a very detailed and complete solution to cross-domain issues (with examples). It has certain reference value. Friends in need can refer to it. I hope it will be helpful to you.

Cross-domain, a common problem

Brief description

As a front-end rookie, I only know JSONP and CORS in cross-domain. Didn't understand it in depth. But as spring recruitment gets closer, even rookies have to flap their wings. I have carefully studied cross-domain issues in recent days and wrote this article, hoping to be helpful to developers. Before reading this article, I hope you have some knowledge of the following.

Browser Origin Policy

nodejs

iframe

docker, nginx

Why should we study cross-domain issues

Because the browser's same-origin policy stipulates that clients in a certain domain cannot read or write resources in another domain without explicit authorization. In actual development, the front-end and back-end are often separated from each other, and the front-end and back-end project deployments are often not within a server or under different ports of a server. If the front end wants to obtain the data from the back end, it must initiate a request. If it is handled properly, it will be constrained by the browser's same-origin policy. The backend can receive the request and return data, but the frontend cannot receive the data.

Multiple cross-domain methods

Cross-domain can be roughly divided into two purposes

When the front-end and back-end are separated, the front-end uses the Cross-domain

Cross-domain for front-end page communication in different domains

Cross-domain for front-end and back-end separation

Cross Origin Resource Share (CORS )

CORS is a cross-domain resource sharing solution. In order to solve cross-domain problems, by adding a series of request headers and response headers, cross-site data transmission is standardized and secure

Request The header mainly includes

The Origin header indicates the source domain name of the cross-domain request in a cross-domain request or a pre-request. The Access-Control-Request-Method header is used to indicate the actual HTTP method used for cross-domain requests Access-Control-Request-Headers is used to inform the server to initiate a request in advance. The request header information that will be carried in the cross-domain request
Request header Explanation
# #Origin
Access-Control-Request-Method
Access-Control-Request-Headers

The response header mainly includes

Response headerExplanation##Access-Control-Allow-OriginAccess-Control-Expose-HeadersAccess-Control-Max-AgeAccess-Control-Allow-Methods

How to use

  • The client only needs to set the request header according to the specification.

  • The server identifies and returns the corresponding response header according to the specification, or installs the corresponding plug-in, modifies the corresponding framework configuration file, etc. It depends on the language and framework used by the server

SpringBoot CORS setting example

A piece of code about CORS configuration in a spring boot project

HttpServletResponse httpServletResponse = (HttpServletResponse) response;
        String temp = request.getHeader("Origin");
        httpServletResponse.setHeader("Access-Control-Allow-Origin", temp);
        // 允许的访问方法
        httpServletResponse.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE, PATCH");
//         Access-Control-Max-Age 用于 CORS 相关配置的缓存
        httpServletResponse.setHeader("Access-Control-Max-Age", "3600");
        httpServletResponse.setHeader("Access-Control-Allow-Headers",
                "Origin, X-Requested-With, Content-Type, Accept,token");
        httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");

JSONP Cross-domain

The principle of jsonp is to use the <script> tag in HTML to introduce resources across domains. Therefore, a <srcipt> tag is dynamically created, and src is the function name of the destination interface get data packet to process data. After receiving the GET request, the backend parses and returns the function name (data) to the front end. The front end<script> tag dynamically executes the processing function<br/>Observe the following code</script>

Front-end code

nbsp;html>


    <meta>
    <title>Title</title>


<script>
    var script = document.createElement(&#39;script&#39;);
    script.type = &#39;text/javascript&#39;;

    // 传参并指定回调执行函数为getData
    script.src = &#39;http://localhost:8080/users?username=xbc&callback=handleData&#39;;
    document.body.appendChild(script);
    // 回调执行函数
    function handleData(res) {
        data = JSON.stringify(res)
        console.log(data);
    }
</script>

Backend Code (nodejs)

var querystring = require('querystring');
var http = require('http');
var server = http.createServer();

server.on('request', function(req, res) {
    var params = querystring.parse(req.url.split('?')[1]);
    var fn = params.callback;

    // jsonp返回设置
    res.writeHead(200, { 'Content-Type': 'text/javascript' });
    var data = {
        user: 'xbc',
        password: '123456'
    }
    res.write(fn + '(' + JSON.stringify(data) + ')');

    res.end();
});

server.listen('8080');
console.log('Server is running at port 8080...');

In this example, the res received by the front desk is like this

Ultra-detailed complete solution to cross-domain problems (with examples)

The front-end page is like this

Ultra-detailed complete solution to cross-domain problems (with examples)

##Note

Since JSONP uses , then it can only Supports GET requests. Other requests cannot be implemented

nginx reverse proxy realizes cross-domain

Ideas

Since the browser has same-origin policy restrictions, then we put the front-end project Isn’t it enough to put the api interface address requested by the front end under the same origin? Combined with the reverse proxy provided by the web server, cross-domain problems can be solved without any configuration on the front end or back end.

Take nginx as an example

The real background address of the backend:

http://xxx.xxx.xxx.xxx:8085 The background address uses the spring boot project deployed by tomcat Named gsms_test

nginx server address:

http://xxx.xxx.xxx.xxx:8082

Both tomcat and nginx are used Set up by docker and do port forwarding

Conditions of use: The development environment is a linux system

nginx

/etc/nginx/conf.d/default.confThe configuration code is as follows

server {
    listen       80;
    server_name  localhost;

    #charset koi8-r;
    #access_log  /var/log/nginx/host.access.log  main;

    location / {
        # root   /usr/share/nginx/html/dist; # 前端项目路径
        # index  index.html index.htm;
        proxy_pass http://localhost:8001/; # 前端本机地址,实现自动更新
        autoindex on;
        autoindex_exact_size on;
        autoindex_localtime on;
    }

    location /gsms_test/ {
        proxy_pass 后端真实地址;
    }

    

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    #location ~ \.php$ {
    #    root           html;
    #    fastcgi_pass   127.0.0.1:9000;
    #    fastcgi_index  index.php;
    #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
    #    include        fastcgi_params;
    #}

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny  all;
    #}
}

Pages in different domains communicate across domains

window.name iframe cross-domain

window.name is browsing The data shared by a window in the server will still exist after loading in different pages (or even different domain names) (the value will not change if it is not modified), and can support very long name value (2MB). for example If a page in domain a wants to obtain data from a page in domain b, you can modify the window.name value in domain b. Switch domain a to domain b and switch back again to get the window.name value of domain b. But we definitely don’t want to switch pages back and forth during development, so we have to combine iframe to achieve it.

Example (implemented with thinkjs)

a The domain code is as follows

nbsp;html>


<meta>
<title>A 域</title>


<h1>server A</h1>
<script>
    function getData() {
        var iframe = document.getElementById(&#39;proxy&#39;);
        iframe.onload = function () {
            var name = iframe.contentWindow.name; // 获取iframe窗口里的window.name值
            console.log(name)
        }
        // 由于iframe信息传递也受同源策略限制,所以在window.name被B域修改后,将iframe转回A域下。以便获取iframe的window.name值
        iframe.src = &#39;http://127.0.0.1:8360/sub.html&#39; 
    }
</script>
<iframe>        </iframe>

b The domain code

nbsp;html>


<meta>
<title>New ThinkJS Application</title>


  <h1>server 2</h1>
<script>
  window.name = &#39;user: xbc&#39;;
</script>

Note

Due to the restriction of the same-origin policy, the parent page obtains incomplete information from the cross-domain iframe page. Therefore, after the window.name of the iframe is modified by the B domain, it must be converted to any page under the A domain. (Window.name must not be modified on this side) and is being obtained.

Proxy page iframe realizes cross-domain access

Since mutual access between iframe and parent page is also restricted by the same-origin policy, a proxy page is needed to achieve cross-domain access.

Ultra-detailed complete solution to cross-domain problems (with examples)

I personally think it is a bit troublesome. If you are interested, please see how the front-end uses a proxy page to solve the problem of iframe cross-domain access?

Summary

The above are all cross-domain methods that I have used or tested. There are also cross-domain methods such as postMessage and WebSocket because I have never Contact without explanation. Which methods should be specifically used in the project also need to consider various issues

Access-Control- The Allow-Origin header carries the allowed cross-domain request domain name after server-side verification, which can be a specific domain name or an * (indicating any domain name).
The Access-Control-Expose-Headers header is used to allow response headers to be returned to cross-domain requests List, the content of the response header in the list can be accessed by the browser.
Access-Control-Max-Age is used to tell the browser that the result of the pre-check request can be returned Cache time. During the cache validity period, the browser will use the cached pre-check results to determine whether to send a cross-domain request.
Access-Control-Allow-Methods is used to tell the browser that it can actually send cross-domain requests , the supported request methods can be a specific method list or an * (indicating any method).
SituationMethodOnly GET requestJSONPNo requirements for compatibility and browser versionCORSRequirements for compatibility and browser versioniframe or server reverse proxy (developed in Linux environment)

The above is the detailed content of Ultra-detailed complete solution to cross-domain problems (with examples). For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:segmentfault.com. If there is any infringement, please contact admin@php.cn delete