Home >Operation and Maintenance >Nginx >How to solve cross-domain issues? A brief analysis of common solutions
Cross-domain is a scenario often encountered in development, and it is also a question often discussed in interviews. Mastering common cross-domain solutions and the principles behind them can not only improve our development efficiency, but also make us more comfortable in interviews.
SoLet’s talk to you today about several common ways to solve cross-domain problems from a front-end perspective.
Before talking about cross-domain, let’s first take a look at the components of a URL:
The contents of a URL Composition, usually contains protocol, host name, port number, path, query parameters and anchor parts.
An example of a URL is shown here:
https://www.example.com:8080/path/resource.html?page=1&sort=desc#header
In the above example:
● The protocol is HTTPS
● The hostname is www.example.com
● The port The number is 8080
● The path is /path/resource.html
● The query parameter is page=1&sort=desc
● The anchor point is header
The so-called cross-domain refers to It means that any part of the protocol, host name, and port number in the request URL is different.
Taking the above URL as an example, the following writing methods are considered to be cross-domain with it:
http://www.example.com:8080/ // 协议不同 https://www.example.a.com:8080/ // 主机名不同 https://www.example.com:8081/ // 端口号不同
In fact The occurrence of cross-domain problems is limited by the browser's same-origin policy.
The so-called same-origin policy is actually a security mechanism of the browser, which is used to restrict network requests in a web page to only access files from the same source (the domain name, protocol and port number are the same) resources, the main purpose is to prevent malicious websites from stealing sensitive data from other websites through scripts, and to protect user privacy and security.
When the browser-side script (js file) accesses network resources in other domains, cross-domain problems will occur.
As mentioned earlier, the occurrence of cross-domain problems is limited by the browser’s same-origin policy, so common solutions to cross-domain problems The solution actually revolves around the browser:
In our usual development, is most commonly used to solve cross-domain problems The solution is to use a proxy server.
Proxy serverTo solve the cross-domain problem, we actually grasp the feature that the same-origin policy is only limited to the browser accessing the server, and there is no restriction on the server accessing the server. As an intermediate The server has a request forwarding function.
Specifically, the web page written by the front-end engineer runs on a proxy server built by scaffolding such as webpack. When the front-end web page initiates a network request in the browser, the request is actually sent to the proxy server. , then the proxy server will forward the request to the target server, and then forward the response returned by the target server to the client.
The proxy server plays a relay role in this process and can modify, filter and intercept requests and responses to achieve some specific functions. Because the front-end web page runs on the proxy server, there is no cross-domain problem.
So how does the proxy server forward requests in the online environment and development environment?
In the online environment, we generally use nginx as a reverse proxy to forward the front-end requests forwarded to the target interface.
nginx is a lightweight high-concurrency web server, event-driven, cross-platform, and can be configured on both window and Linux.
The main way it serves as a proxy server to solve cross-domain problems in development is to listen to the running port of the online front-end URL, and then forward the request after encountering a request containing a special tag .
In the development environment, whether it is a front-end project built with the help of webpack or using vite or other scaffolding, the core of solving cross-domain problems is Implemented with the help of http-proxy-middleware middleware. The core of http-proxy-middleware middleware is a further encapsulation of http-proxy.
Here is a sample code that uses http-proxy-middleware to implement the request forwarding function in the project:
const { createProxyMiddleware } = require('http-proxy-middleware'); module.exports = { server: { proxy: { // 将 /api/* 的请求代理到 http://localhost:3000/* '/api': { target: 'http://localhost:3000', changeOrigin: true, pathRewrite: { '^/api': '/' } } } } };
Then we can use native node, use the http-proxy library to build a proxy server Demo with request forwarding function. Interested friends can test and play by themselves:
1. First you need to create a Use the empty folder (named in English) as the project folder, and then use the npm init -y command to upgrade the project to a node project:
npm init -y
2. Next Create an index.html file in the project root directory to initiate cross-domain requests:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>请求转发测试</title> </head> <body> <h1>请求转发测试</h1> <p id="message"></p> <script> fetch('/api/login') .then(response => response.text()) .then(data => { document.getElementById('message').textContent = data; }); </script> </body> </html>
3. Then create a new index in the project root directory .js file to write server-side code.
The index.js file is the core file for implementing a proxy server with request forwarding function.
const http = require('http'); const httpProxy = require('http-proxy'); const fs = require('fs'); const path = require('path'); // 创建代理服务器实例 const proxy = httpProxy.createProxyServer({}); // 创建HTTP服务器 const server = http.createServer((req, res) => { if (req.url === '/' || req.url.endsWith('.html')) { // 读取HTML文件 const filename = path.join(__dirname, 'index.html'); fs.readFile(filename, 'utf8', (err, data) => { if (err) { res.writeHead(500); res.end('Error reading HTML file'); } else { res.writeHead(200, { 'Content-Type': 'text/html' }); res.end(data); } }); } else if (req.url.startsWith('/api')) { // 重写路径,替换跨域关键词 req.url = req.url.replace(/^\/api/, ''); // 将请求转发至目标服务器 proxy.web(req, res, { target: 'http://localhost:3000/', changeOrigin: true, }); } }); // 监听端口 server.listen(8080, () => { console.log('Server started on port 8080'); });
4. Then write the contents of the target servertarget.js file for testing cross-domain access:
const http = require('http'); const server = http.createServer((req, res) => { if (req.url.startsWith('/login')) { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end('我是localhost主机3000端口下的方法,恭喜你访问成功!'); } else { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end('Hello, world!'); } }); server.listen(3000, () => { console.log('Target server is listening on port:3000'); })
5. 打开终端,输入启动目标服务器的命令:
node ./target.js //项目根目录下执行
6. 再开一个终端启动代理服务器,等待浏览器端发起请求就可以啦:
node ./index.js //项目根目录下执行
7. 最后在浏览器里访问http://localhost:8080, 打开控制台即可查看效果:
可以发现,浏览器network模块的网络请求确实是访问的8080端口的方法,但是我们的服务器默默的做了请求转发的功能,并将请求转发获取到的内容返回到了前端页面上。
其实http-proxy是对node内置库http的进一步封装,网络请求的核心部分还是使用http创建一个服务器对象去访问的。感兴趣的同学可以再读读http-proxy的源码~
除了代理服务器这种绕过浏览器同源策略的解决方式外,从前端的角度解决跨域问题还有如下一些常见的方法:
JSONP的原理是通过动态创建3f1c4e4b6b16bbbd69b2ee476dc4f83a标签,向服务器发送请求并在请求URL中传递一个回调函数名(通常是在本地定义的函数名),服务器在返回的数据中将这个回调函数名和实际数据一起封装成一个JavaScript函数的调用,返回给客户端,客户端利用该回调函数对数据进行处理。
JSONP之所以能够跨域请求数据,是因为浏览器对于3f1c4e4b6b16bbbd69b2ee476dc4f83a标签的请求不会受到同源策略的限制。
需要注意的是,使用JSONP技术的前提是服务器需要支持JSONP的方式,即在返回的数据中包含回调函数名和实际数据的封装,否则客户端无法处理返回的数据。
此外,JSONP只支持GET请求,不支持POST等其他HTTP请求方式,因为3f1c4e4b6b16bbbd69b2ee476dc4f83a标签只支持GET请求。
因此JSONP这种方式在我们的开发中使用的场景不多。
CORS全称为Cross-Origin Resource Sharing,它通过HTTP头部信息告诉浏览器哪些跨域请求是被允许的,从而实现安全的跨域访问。
CORS解决跨域需要浏览器端和服务器端的配合。原理是在服务器端设置HTTP头部信息,告诉浏览器允许哪些源(域名、协议、端口)访问服务器上的资源,如果请求的源不在允许的列表中,则浏览器将拒绝访
问。
服务器可以通过设置Access-Control-Allow-Origin、Access-Control-Allow-Headers、Access-Control-Allow-Methods等HTTP头部信息来控制跨域访问权限。
具体地,当浏览器发起跨域请求时,会先发送一个OPTIONS请求(预检请求),询问服务器是否允许该跨域请求。
服务器接收到该请求后,根据请求中的HTTP头部信息判断是否允许该请求。
如果允许,则返回相应的HTTP头部信息告知浏览器可以继续发送真正的跨域请求。如果不允许,则返回一个错误状态码,告诉浏览器该请求被拒绝。
预检请求时,请求头常见参数有:
请求头 | 值 |
---|---|
Origin | 表示请求的源地址,即发起跨域请求的域名 |
Access-Control-Request-Method | 表示实际请求采用的HTTP方法 |
Access-Control-Request-Headers | 表示实际请求中所携带的额外请求头信息,比如自定义请求头等 |
预检请求时,响应头常见参数有:
响应头 | 值 |
---|---|
Access-Control-Allow-Origin | *、origin... |
Access-Control-Allow-Headers | POST, GET, PUT, DELETE, OPTIONS |
Access-Control-Allow-Methods | Content-Type, Authorization.. |
Access-Control-Allow-Credentials | true |
Access-Control-Max-Age | 86400 |
It should be noted that the prerequisite for using CORS is that the server needs to set relevant HTTP header information and the browser supports CORS. In addition, CORS only supports modern browsers, and some older browsers may not support CORS.
such as WebSocket, postMessage, etc.
In recent years, with the rapid development of front-end and back-end technology, independent development of front-end and back-end has gradually become the mainstream development model. The front-end and back-end programmers only need to agree on the interface, then develop the corresponding modules independently, and finally perform joint debugging of the interface. During the interface joint debugging process, cross-domain development in the development environment is a problem that needs to be solved.
In addition, after the current back-end project is packaged and moved to the cloud, when the front-end page accesses the back-end interface through the online address, cross-domain in the online environment is also a problem that needs to be solved .
This article describes several common cross-domain solutions. Each of these solutions has its own advantages and disadvantages. You can choose a suitable solution according to the actual situation to solve the corresponding cross-domain problems~
Recommended tutorial: nginx tutorial
The above is the detailed content of How to solve cross-domain issues? A brief analysis of common solutions. For more information, please follow other related articles on the PHP Chinese website!