Rumah >Operasi dan penyelenggaraan >Nginx >Bagaimana untuk menyelesaikan isu merentas domain? Analisis ringkas penyelesaian biasa
Merentas domain ialah senario yang sering dihadapi dalam pembangunan, dan ia juga merupakan isu yang sering dibincangkan dalam temu bual. Menguasai penyelesaian merentas domain biasa dan prinsip di sebaliknya bukan sahaja boleh meningkatkan kecekapan pembangunan kami, tetapi juga menjadikan kami lebih selesa dalam temu duga.
Jadi hari ini saya akan bercakap dengan anda tentang beberapa cara biasa untuk menyelesaikan isu merentas domain dari perspektif bahagian hadapan.
Sebelum bercakap tentang merentas domain, mari kita lihat dahulu komponen URL:
URL Ia biasanya mengandungi protokol, nama hos, nombor port, laluan, parameter pertanyaan dan sauh .
Contoh URL ditunjukkan di sini:
https://www.example.com:8080/path/resource.html?page=1&sort=desc#header
Dalam contoh di atas:
● Protokolnya ialah HTTPS
● Nama hos ialah www.example.com
● Nombor port ialah 8080
● Laluan ialah /path/resource.html
● Parameter pertanyaan ialah page=1&sort=desc
● Titik anchor ialah pengepala
Yang dipanggil domain silang, Ini bermakna mana-mana bahagian protokol, nama hos dan nombor port dalam URL permintaan adalah berbeza.
Mengambil URL di atas sebagai contoh, kaedah penulisan berikut dianggap sebagai domain silang dengannya:
http://www.example.com:8080/ // 协议不同 https://www.example.a.com:8080/ // 主机名不同 https://www.example.com:8081/ // 端口号不同
Malahkejadian masalah merentas domain dihadkan oleh dasar asal penyemak imbas yang sama.
所谓同源策略,其实是浏览器的一种安全机制,用于限制一个网页中的网络请求仅能够访问来自同一源(域名、协议和端口号均相同)的资源,主要目的是防止恶意网站通过脚本窃取其他网站的敏感数据,保障用户的隐私和安全。
Apabila skrip sebelah penyemak imbas (fail js) mengakses sumber rangkaian dalam domain lain, masalah merentas domain akan berlaku.
Seperti yang dinyatakan sebelum ini, berlakunya masalah merentas domain dihadkan oleh dasar asal penyemak imbas yang sama, jadi ada adalah cara biasa untuk menyelesaikan masalah merentas domain Penyelesaiannya sebenarnya berkisar pada penyemak imbas:
Dalam pembangunan biasa kami, adalah paling banyak. biasa digunakan untuk menyelesaikan masalah merentas domain Penyelesaiannya adalah dengan menggunakan pelayan proksi .
Pelayan proksi menyelesaikan masalah merentas domain dengan benar-benar merebut ciri bahawa dasar asal yang sama hanya terhad kepada penyemak imbas yang mengakses pelayan dan tiada sekatan ke atas pelayan mengakses pelayan berfungsi sebagai perantara Pelayan mempunyai fungsi pemajuan permintaan .
Khususnya, halaman web yang ditulis oleh jurutera bahagian hadapan berjalan pada pelayan proksi yang dibina dengan perancah seperti webpack Apabila halaman web bahagian hadapan memulakan permintaan rangkaian dalam penyemak imbas, permintaan itu sebenarnya dihantar kepada pelayan proksi , maka pelayan proksi akan memajukan permintaan kepada pelayan sasaran, dan kemudian memajukan respons yang dikembalikan oleh pelayan sasaran kepada klien.
Pelayan proksi memainkan peranan geganti dalam proses ini dan boleh mengubah suai, menapis serta memintas permintaan dan respons untuk mencapai beberapa fungsi tertentu. Oleh kerana halaman web bahagian hadapan berjalan pada pelayan proksi, tiada masalah merentas domain.
Jadi, bagaimanakah pelayan proksi menghantar permintaan dalam persekitaran dalam talian dan persekitaran pembangunan?
Dalam persekitaran dalam talian, kami biasanya menggunakan nginx sebagai proksi terbalik untuk memajukan permintaan bahagian hadapan yang dimajukan kepada antara muka sasaran.
nginx ialah pelayan web konkurensi tinggi yang ringan, dipacu acara, merentas platform dan boleh dikonfigurasikan pada kedua-dua tetingkap dan Linux.
Cara utama ia berfungsi sebagai pelayan proksi untuk menyelesaikan masalah merentas domain dalam pembangunan ialah mendengar port yang sedang dijalankan bagi URL bahagian hadapan dalam talian, dan kemudian memajukan permintaan apabila ia menemui a permintaan yang mengandungi tag khas .
Dalam persekitaran pembangunan, sama ada ia adalah projek hadapan yang dibina dengan bantuan webpack atau menggunakan vite atau perancah lain, teras menyelesaikan masalah merentas domain Dilaksanakan dengan bantuan http-proxy-middleware middleware. Teras http-proxy-middleware middleware ialah enkapsulasi lanjut http-proxy.
Di sini kami mula-mula menunjukkan kod sampel untuk menggunakan http-proxy-middleware dalam projek untuk melaksanakan fungsi pemajuan permintaan:
const { createProxyMiddleware } = require('http-proxy-middleware'); module.exports = { server: { proxy: { // 将 /api/* 的请求代理到 http://localhost:3000/* '/api': { target: 'http://localhost:3000', changeOrigin: true, pathRewrite: { '^/api': '/' } } } } };
Kemudian kami boleh melakukannya sendiri Gunakan nod asli dan gunakan perpustakaan proksi http untuk membina pelayan proksi Demo dengan fungsi pemajuan permintaan Rakan yang berminat boleh menguji dan bermain sendiri :
1. Mula-mula anda perlu Cipta folder kosong (dinamakan dalam bahasa Inggeris) sebagai folder projek, dan kemudian gunakan perintah npm init -y untuk menaik taraf projek kepada projek nod:
npm init -y
2. Kemudian buat fail index.html dalam direktori akar projek untuk memulakan permintaan merentas domain:
<!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. Kemudian buat fail dalam direktori akar projek Cipta fail index.js baharu untuk menulis kod sebelah pelayan.
Fail index.js ialah fail teras untuk melaksanakan pelayan proksi dengan fungsi pemajuan permintaan.
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. Kemudian tulis kandungan pelayan sasaran fail target.js untuk menguji akses merentas domain:
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 |
Perlu diambil perhatian bahawa prasyarat untuk menggunakan CORS ialah pelayan perlu menetapkan maklumat pengepala HTTP yang berkaitan dan penyemak imbas menyokong CORS. Selain itu, CORS hanya menyokong penyemak imbas moden dan sesetengah penyemak imbas lama mungkin tidak menyokong CORS.
seperti WebSocket, postMessage, dsb.
Dalam beberapa tahun kebelakangan ini, dengan perkembangan pesat teknologi front-end dan back-end, pembangunan bebas front-end dan back-end telah beransur-ansur menjadi arus perdana model pembangunan. Pengaturcara bahagian hadapan dan belakang hanya perlu bersetuju dengan antara muka, kemudian membangunkan modul yang sepadan secara bebas, dan akhirnya melakukan penyahpepijatan bersama antara muka. Semasa proses penyahpepijatan bersama antara muka, pembangunan merentas domain dalam persekitaran pembangunan merupakan masalah yang perlu diselesaikan.
Selain itu, selepas projek bahagian belakang semasa dibungkus dan dialihkan ke awan, apabila halaman hujung hadapan mengakses antara muka hujung belakang melalui alamat dalam talian, Rentas domain dalam persekitaran dalam talian juga merupakan masalah yang perlu diselesaikan .
Artikel ini menerangkan beberapa penyelesaian merentas domain yang biasa Setiap penyelesaian ini mempunyai kelebihan dan keburukan tersendiri Anda boleh memilih penyelesaian yang sesuai mengikut situasi sebenar untuk menyelesaikan masalah merentas domain yang sepadan~
Tutorial disyorkan: tutorial nginx
Atas ialah kandungan terperinci Bagaimana untuk menyelesaikan isu merentas domain? Analisis ringkas penyelesaian biasa. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!