Condivisione della tecnologia

Comprendere a fondo il cross-domain front-end

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

 

Sommario

1Politica sulla stessa origine del browser

1.1 Panoramica sulla politica della stessa origine

1.2 Cos'è l'origine?

2. Quali sono le restrizioni sulle transazioni tra domini?

2.1 Limitare l'accesso al DOM

2.2 Limitare l'accesso ai cookie

2.3 Limitare Ajax per ottenere dati

3 punti da notare

4CORS risolve i problemi tra domini Ajax

4.1Panoramica CORS

4.2CORS risolve semplici richieste interdominio

4.3 Richieste semplici e richieste complesse

4.4CORS risolve richieste complesse tra domini

4.5 Utilizzare la libreria cors per completare rapidamente la configurazione

5JSONP risolve i problemi tra domini

6Configurare il proxy per risolvere problemi tra domini

6.1 Configura tu stesso il server proxy

6.2 Utilizzare Nginx per creare un server proxy

6.3 Costruisci un server con l'aiuto di impalcature


Codice indirizzo git clone https://gitee.com/childe-jia/cross-domain-test.git

1Politica sulla stessa origine del browser

1.1 Panoramica sulla politica della stessa origine


La politica della stessa origine è una politica che i browser seguono per garantire la sicurezza delle risorse. Questa politica impone alcune restrizioni sull'accesso alle risorse.
Descrizione della politica della stessa origine del W3C:Politica della stessa origine

1.2 Cos'è l'origine?


1 componenti di origine

immagine.png


2Nella tabella seguente solo le due sorgenti dell'ultima riga hanno la stessa origine.

Fonte 1

Fonte 2

È omologa?

http://www.xyz.com/home

https://www.xyz.com/home

⛔Non omogeneo️

http://www.xyz.com/home

http://mail.xyz.com/home

⛔Non omogeneo

http://www.xyz.com:8080/home

http://www.xyz.com:8090/home

⛔Non omogeneo

http://www.xyz.com:8080/home

http://www.xyz.com:8080/search

✅Stessa origine︎

 

3 richiesta di origine

immagine.png


4 Richiesta non originaria

immagine.png


5 Riepilogo: se la "sorgente" non è coerente con la "sorgente di destinazione", significa "non-sorgente", nota anche come "eterosorgente" o "interdominio"

2. Quali sono le restrizioni sulle transazioni tra domini?


Ad esempio, se ci sono due fonti: "Fonte A" e "Fonte B", che sono "origine diversa", il browser avrà le seguenti restrizioni:

2.1 Limitare l'accesso al DOM

Lo script della "Sorgente A" non può accedere al DOM della "Sorgente B".

  1. <!-- <iframe id="framePage" src="./demo.html"></iframe> -->
  2. <iframe id="framePage" src="https://www.baidu.com"></iframe>
  3. <script type="text/javascript" >
  4. function showDOM(){
  5. const framePage = document.getElementById('framePage')
  6. console.log(framePage.contentWindow.document) //同源的可以获取,非同源的无法获取
  7. }
  8. </script>

2.2 Limitare l'accesso ai cookie

La "Fonte A" non può accedere al cookie della "Fonte B"

  1. <iframe id="baidu" src="http://www.baidu.com" width="500" height="300"></iframe>
  2. <script type="text/javascript" >
  3. // 访问的是当前源的cookie,并不是baidu的cookie
  4. console.log(document.cookie)
  5. </script>

2.3 Limitare Ajax per ottenere dati

La "Fonte A" può inviare richieste alla "Fonte B", ma non può ottenere i dati di risposta dalla "Fonte B".

  1. const url = 'https://www.toutiao.com/hot-event/hot-board/?origin=toutiao_pc'
  2. let result = await fetch(url)
  3. let data = await result.json();
  4. console.log(data)

Nota: tra le restrizioni di cui sopra, quella del browser sull'acquisizione dei dati Ajax ha l'impatto maggiore e viene spesso riscontrata nello sviluppo effettivo.

3 punti da notare

  • 1Le restrizioni tra domini esistono solo sul lato browser e non esistono restrizioni tra domini sul lato server.
  • 2 Anche se si tratta di domini incrociati, le richieste Ajax possono essere emesse normalmente, ma i dati di risposta non verranno consegnati allo sviluppatore.
  • 3<link> , <script>、<img>...... 这些标签发出的请求也可能跨域,只不过浏览器对标签跨域不做严格限制,对开发几乎无影响

immagine.png

4CORS risolve i problemi tra domini Ajax

4.1Panoramica CORS

Il nome completo di CORS: Cross-Origin Resource Sharing (Condivisione di risorse incrociate) è un insieme di specifiche utilizzate per controllare la verifica del browser delle richieste tra domini. Il server segue la specifica CORS e aggiunge intestazioni di risposta specifiche per controllare la verifica del browser. Le regole generali sono le seguenti:
●Il server rifiuta esplicitamente le richieste tra domini o non lo indica e il browser non supera la verifica.
●Il server indica chiaramente che le richieste tra domini sono consentite e la verifica del browser viene superata.
Nota: l'utilizzo di CORS per risolvere problemi tra domini è il modo più ortodosso e richiede che il server sia "uno dei nostri".


4.2CORS risolve semplici richieste interdominio

L'idea generale: quando il server risponde, esprime chiaramente che una determinata fonte è autorizzata ad avviare richieste tra domini aggiungendo l'intestazione di risposta Access-Control-Allow-Origin, quindi il browser la passa direttamente durante la verifica.

immagine.png

Codice core lato server (prendi Express Framework come esempio):

  1. // 处理跨域中间件
  2. function corsMiddleWare(req,res,next){
  3. // 允许 http://127.0.0.1:5500 这个源发起跨域请求
  4. // res.setHeader('Access-Control-Allow-Origin','http://127.0.0.1:5500')
  5. // 允许所有源发起跨域请求
  6. res.setHeader('Access-Control-Allow-Origin','*')
  7. next()
  8. }
  9. // 配置路由并使用中间件
  10. app.get('/',corsMiddleWare,(req,res)=>{
  11. res.send('hello!')
  12. })

4.3 Richieste semplici e richieste complesse

Il CORS dividerà le richieste in due categorie: ① richieste semplici e ② richieste complesse.

semplice richiesta

Richiesta complessa

✅Il metodo di richiesta (metodo) è: GET, HEAD, POST

1 è una richiesta semplice o una richiesta complessa.
2 Le richieste complesse invieranno automaticamente le richieste di preflight.

✅I campi dell'intestazione della richiesta devono essere conformi"Specifiche di sicurezza CORS"
Breve nota: finché l'intestazione della richiesta non viene modificata manualmente, generalmente può essere conforme a questa specifica.

✅Il valore Content-Type dell'intestazione della richiesta può essere solo i seguenti tre:
●testo/semplice
●multipart/form-data
●applicazione/x-www-form-urlencoded

Per quanto riguarda le richieste di preflight:

  • 1Tempi di invio: la richiesta preliminare viene inviata prima dell'effettiva richiesta interdominio e viene avviata automaticamente dal browser.
  • 2 Funzione principale: utilizzata per confermare al server se consentire la successiva richiesta interdominio.
  • 3Processo di base: avviare innanzitutto una richiesta OPTIONS. Se supera il controllo preliminare, continuare ad avviare l'effettiva richiesta interdominio.
  • 4 Contenuto dell'intestazione della richiesta: una richiesta di preflight OPTIONS solitamente contiene le seguenti intestazioni della richiesta:

Intestazione della richiesta

Senso

Origine

La fonte della richiesta

Metodo di richiesta di controllo degli accessi

Il metodo HTTP effettivamente richiesto

Intestazioni di richiesta di controllo di accesso

Intestazioni personalizzate utilizzate nella richiesta effettiva (se presenti)

4.4CORS risolve richieste complesse tra domini

1 Passo uno: il server passa prima la richiesta di preflight del browser Il server deve restituire la seguente intestazione di risposta:

intestazione della risposta

Senso

Controllo-accesso-consenti-origine

fonti consentite

Metodi di controllo degli accessi consentiti

metodi consentiti

Controllo-accesso-consenti-intestazioni

Intestazioni personalizzate consentite

Controllo-Accesso-Età-Massima

Tempo di memorizzazione nella cache dei risultati per le richieste di verifica preliminare (facoltativo)

immagine.png

2 Passaggio 2: gestire la richiesta interdominio effettiva (nello stesso modo in cui gestisci le richieste interdominio semplici)

immagine.png

Codice principale del server:

  1. // 处理预检请求
  2. app.options('/students', (req, res) => {
  3. // 设置允许的跨域请求源
  4. res.setHeader('Access-Control-Allow-Origin', 'http://127.0.0.1:5500')
  5. // 设置允许的请求方法
  6. res.setHeader('Access-Control-Allow-Methods', 'GET')
  7. // 设置允许的请求头
  8. res.setHeader('Access-Control-Allow-Headers', 'school')
  9. // 设置预检请求的缓存时间(可选)
  10. res.setHeader('Access-Control-Max-Age', 7200)
  11. // 发送响应
  12. res.send()
  13. })
  14. // 处理实际请求
  15. app.get('/students', (req, res) => {
  16. // 设置允许的跨域请求源
  17. res.setHeader('Access-Control-Allow-Origin', 'http://127.0.0.1:5500')
  18. // 随便设置一个自定义响应头
  19. res.setHeader('abc',123)
  20. // 设置允许暴露给客户端的响应头
  21. res.setHeader('Access-Control-Expose-Headers', 'abc')
  22. // 打印请求日志
  23. console.log('有人请求/students了')
  24. // 发送响应数据
  25. res.send(students)
  26. })

4.5 Utilizzare la libreria cors per completare rapidamente la configurazione

Nella configurazione precedente, è necessario configurare personalmente l'intestazione della risposta oppure incapsulare manualmente il middleware. Con la libreria cors è possibile completare la configurazione in modo più pratico.

●Installa cors

npm i cors

●Configurazione semplice cor

app.use(cors())

●Configurare completamente cors

  1. // cors中间件配置
  2. const corsOptions = {
  3. origin: 'http://127.0.0.1:5500', // 允许的源
  4. methods: ['GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'OPTIONS'], // 允许的方法
  5. allowedHeaders: ['school'], // 允许的自定义头
  6. exposedHeaders: ['abc'], // 要暴露的响应头
  7. optionsSuccessStatus: 200 // 预检请求成功的状态码
  8. };
  9. app.use(cors(corsOptions)); // 使用cors中间件

Per impostazione predefinita, js non può accedere all'intestazione della risposta impostata dal backend e deve essere esposto dal backend.

5JSONP risolve i problemi tra domini

1 Panoramica di JSONP: utilizza JSONP<script>标签可以跨域加载脚本,且不受严格限制的特性,可以说是程序员智慧的结晶,早期一些浏览器不支持 CORS 的时,可以靠 JSONP 解决跨域。


2Processo di base:

  • ○Passaggio uno: il cliente crea un file<script>标签,并将其src属性设置为包含跨域请求的 URL,同时准备一个回调函数,这个回调函数用于处理返回的数据。
  • ○Passaggio 2: dopo aver ricevuto la richiesta, il server incapsula i dati nella funzione di callback e li restituisce.
  • ○Passaggio 3: viene richiamata la funzione di callback del client e i dati vengono passati alla funzione di callback sotto forma di parametri.

3Illustrazione:

immagine.png

4 esempi di codice:

  1. <button onclick="getTeachers()">获取数据</button>
  2. <script type="text/javascript" >
  3. function callback(data){
  4. console.log(data)
  5. }
  6. function getTeachers(url){
  7. // 创建script元素
  8. const script = document.createElement('script')
  9. // 指定script的src属性
  10. script.src= 'http://127.0.0.1:8081/teachers'
  11. // 将script元素添加到body中触发脚本加载
  12. document.body.appendChild(script)
  13. // script标签加载完毕后移除该标签
  14. script.onload = ()=>{
  15. script.remove()
  16. }
  17. }
  18. </script>

5jQuery incapsulato jsonp

?callback=?' è un formato fisso e verrà analizzato automaticamente

  1. $.getJSON('http://127.0.0.1:8081/teachers?callback=?',(data)=>{
  2. console.log(data)
  3. })

6Configurare il proxy per risolvere problemi tra domini

6.1 Configura tu stesso il server proxy

Non ci sono problemi tra domini tra i server. È necessario utilizzare Express per avviare le risorse statiche per garantire che il server e la pagina siano nella stessa origine.

  1. // 启动静态资源 让服务器跟页面同一个源
  2. app.use(express.static("./public"));

Configura il proxy con http-proxy-middleware

  1. const { createProxyMiddleware } = require('http-proxy-middleware');
  2. app.use('/api',createProxyMiddleware({
  3. target:'https://www.toutiao.com',
  4. changeOrigin:true,
  5. pathRewrite:{
  6. '^/api':''
  7. }

 

vantaggio:

  • Funzioni avanzate: http-proxy-middleware fornisce numerose opzioni di configurazione per soddisfare le varie esigenze del proxy.
  • È possibile configurare più proxy in modo flessibile: è possibile configurare più server proxy, corrispondenti a diversi percorsi di interfaccia.
  • Può intercettare le richieste: le richieste possono essere intercettate e modificate tramite funzioni di elaborazione personalizzate.

discordanza:

  • La configurazione è relativamente complessa: è necessario comprendere le regole di configurazione e i parametri della libreria http-proxy-middleware.
  • Non adatto per ambienti di produzione: http-proxy-middleware viene utilizzato principalmente in ambienti di sviluppo e non è adatto per ambienti di produzione.

scene da utilizzare:

  • Adatto a progetti front-end che utilizzano qualsiasi strumento di creazione e funziona con qualsiasi server di sviluppo.
  • Adatto a scenari in cui è necessario configurare più server proxy in modo flessibile.
  • Adatto a scenari in cui le richieste devono essere intercettate e modificate.

6.2 Utilizzare Nginx per creare un server proxy

L'idea generale: lasciare che nginx svolga due ruoli, sia come server di contenuti statici che come server proxy.

Modifica la configurazione di nginx come segue. Tieni presente che la directory root di nginx preferibilmente non è l'unità C.

  1. # 配置nginx根目录
  2. location / {
  3. root D:dist;
  4. index index.html index.htm;
  5. }
  6. # 配置代理
  7. location /dev/ {
  8. # 设置代理目标
  9. proxy_pass http://sph-h5-api.atguigu.cn/;
  10. }

2 Modificare il progetto front-end in modo che tutte le richieste vengano inoltrate a /dev e quindi riconfezionate

  1. const request = axios.create({
  2. baseURL:'/dev',
  3. timeout:10000
  4. })

Quindi accedi direttamente al server nginx. Ad esempio, se nginx è in esecuzione sulla porta 8099, access

http://localhost:8099

Quindi incontrerai il problema di aggiornamento 404, aggiungi la configurazione nginx per risolverlo

  1. # 配置nginx根目录
  2. location / {
  3. root D:dist;
  4. index index.html index.htm;
  5. try_files $uri $uri/ /index.html; # 解决刷新404
  6. }
  7. # 配置代理
  8. location /dev/ {
  9. # 设置代理目标
  10. proxy_pass http://sph-h5-api.atguigu.cn/;
  11. }

L'aggiunta di questi due "/" elimina dev

6.3 Costruisci un server con l'aiuto di impalcature

1. Utilizzare il file vue.config.js per configurare il proxy:

Crea un file vue.config.js nella directory root del progetto Vue e aggiungi il seguente codice:

  1. module.exports = {
  2. devServer: {
  3. proxy: {
  4. '/api': {
  5. target: 'http://api.example.com',
  6. changeOrigin: true,
  7. pathRewrite: {
  8. '^/api': ''
  9. }
  10. }
  11. }
  12. }
  13. }

Nel codice precedente usiamodevServer Elementi di configurazione per configurare il server proxy.InproxyLe proprietà vengono utilizzate per configurare le regole del proxy,/apiIndica il percorso dell'interfaccia che richiede l'inoltro.targetL'attributo rappresenta l'indirizzo del server di destinazione del proxy,changeOriginL'attributo indica se modificare l'indirizzo di origine della richiesta.pathRewriteProprietà utilizzata per sovrascrivere il percorso richiesto.

vantaggio:

  • Configurazione semplice: utilizzando la configurazione proxy di webpack-dev-server, è necessario eseguire solo una configurazione semplice nel file di configurazione webpack.
  • Funzionalità complete: webpack-dev-server fornisce una vasta gamma di opzioni di configurazione per soddisfare la maggior parte delle esigenze dei proxy.
  • Può intercettare le richieste: le richieste possono essere intercettate e modificate tramite funzioni di elaborazione personalizzate.

discordanza:

  • Il server deve essere riavviato: dopo aver modificato la configurazione, webpack-dev-server deve essere riavviato affinché abbia effetto.
  • Non adatto ad ambienti di produzione: webpack-dev-server viene utilizzato principalmente in ambienti di sviluppo e non è adatto ad ambienti di produzione.

scene da utilizzare:

  • È adatto per progetti front-end realizzati utilizzando webpack e avviando il server di sviluppo tramite webpack-dev-server.
  • È adatto per scenari che richiedono una semplice configurazione del proxy e non necessitano di modificare frequentemente la configurazione del proxy.