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
Request header |
Explanation |
# #Origin
| The Origin header indicates the source domain name of the cross-domain request in a cross-domain request or a pre-request. |
Access-Control-Request-Method
| The Access-Control-Request-Method header is used to indicate the actual HTTP method used for cross-domain requests |
Access-Control-Request-Headers
| 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 |
The response header mainly includes
Response header | Explanation |
##Access-Control-Allow-Origin
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). |
|
Access-Control-Expose-Headers
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
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
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). |
|
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");
Copy after login
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('script');
script.type = 'text/javascript';
// 传参并指定回调执行函数为getData
script.src = 'http://localhost:8080/users?username=xbc&callback=handleData';
document.body.appendChild(script);
// 回调执行函数
function handleData(res) {
data = JSON.stringify(res)
console.log(data);
}
</script>
Copy after login
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...');
Copy after login
In this example, the res received by the front desk is like this
The front-end page is like this
##Note
Since JSONP uses , then it can only Supports GET requests. Other requests cannot be implementednginx 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 exampleThe 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 forwardingConditions of use: The development environment is a linux systemnginx /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;
#}
}
Copy after login
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('proxy');
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 = 'http://127.0.0.1:8360/sub.html'
}
</script>
<iframe> </iframe>
Copy after login
b The domain code
nbsp;html>
<meta>
<title>New ThinkJS Application</title>
<h1>server 2</h1>
<script>
window.name = 'user: xbc';
</script>
Copy after login
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 accessSince 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.
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
Situation | Method |
Only GET request | JSONP |
No requirements for compatibility and browser version | CORS |
Requirements for compatibility and browser version | iframe 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!