Dieser Artikel bietet Ihnen eine sehr detaillierte und vollständige Lösung für domänenübergreifende Probleme (mit Beispielen). Ich hoffe, dass er für Freunde in Not hilfreich ist.
Domänenübergreifende, alltägliche Probleme
Kurze Beschreibung
Als Front-End-Neuling kenne ich nur JSONP und CORS in Cross -Domäne. Ich habe es nicht im Detail verstanden. Doch je näher die Rekrutierung im Frühjahr rückt, desto mehr müssen selbst Neulinge mit den Flügeln schlagen. Ich habe mich in den letzten Tagen sorgfältig mit domänenübergreifenden Problemen befasst und diesen Artikel geschrieben, in der Hoffnung, für Entwickler hilfreich zu sein. Ich hoffe, dass Sie vor dem Lesen dieses Artikels einige Kenntnisse über Folgendes haben.
Browser Same Origin Policy
nodejs
iframe
Docker, Nginx
Warum sollten wir domänenübergreifende Probleme untersuchen?
Weil die Same-Origin-Richtlinie des Browsers vorsieht, dass Clients in einer bestimmten Domäne ohne ausdrückliche Autorisierung keine Ressourcen in einer anderen Domäne lesen oder schreiben können. In der tatsächlichen Entwicklung sind Front-End und Back-End häufig voneinander getrennt, und die Bereitstellung von Front-End- und Back-End-Projekten erfolgt häufig nicht innerhalb eines Servers oder unter verschiedenen Ports eines Servers. Wenn das Front-End die Daten vom Back-End erhalten möchte, muss es eine Anfrage initiieren. Wenn diese ordnungsgemäß verarbeitet wird, wird sie durch die Same-Origin-Richtlinie des Browsers eingeschränkt. Das Backend kann die Anforderungs- und Rückgabedaten empfangen, das Frontend kann die Daten jedoch nicht empfangen.
Mehrere domänenübergreifende Methoden
Domänenübergreifend kann grob in zwei Zwecke unterteilt werden
Wenn Front-End und Back-End getrennt sind , das Front-End verwendet domänenübergreifend
Domänenübergreifend für die Front-End-Seitenkommunikation in verschiedenen Domänen
Domänenübergreifend für Front-End- und Back-End-Trennung
Cross Origin Resource Share (CORS))
CORS ist eine domänenübergreifende Lösung zur Ressourcenfreigabe, um domänenübergreifende Probleme durch Hinzufügen einer Reihe von Anforderungsheadern und Antworten zu lösen Header, standortübergreifende Datenübertragung ist standardisiert und sicher
Anfrage-Header umfassen hauptsächlich
Anfrage-Header | Erklärung | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
|
Der Origin-Header gibt den Namen der Quelldomäne an der domänenübergreifenden Anfrage in einer domänenübergreifenden Anfrage oder einer Voranfrage. | ||||||||||
Access-Control-Request-Method | Der Header Access-Control-Request-Method wird verwendet, um die Verwendung von anzuzeigen domänenübergreifende Anfragen. Tatsächliche HTTP-Methode | ||||||||||
Access-Control-Request-Headers
|
Access-Control-Request-Headers wird verwendet Informieren Sie den Server bei einer Anfrage im Voraus über die Anforderungsheaderinformationen, die in der zu initiierenden domänenübergreifenden Anforderung enthalten sein werden |
Antwortheader | Erklärung th> |
---|---|
Access-Control-Allow-Origin | Der Header Access-Control-Allow-Origin trägt die Nach der serverseitigen Überprüfung ist eine domänenübergreifende Anforderung eines Domänennamens zulässig. Dies kann ein bestimmter Domänenname oder ein * sein (was einen beliebigen Domänennamen anzeigt). |
Access-Control-Expose-Headers | Der Access-Control-Expose-Headers-Header wird verwendet, um das Kreuzen von Rückgaben zu ermöglichen -Domain-Anfragen Eine Liste von Antwortheadern. Der Browser kann nur auf den Inhalt der Antwortheader in der Liste zugreifen. |
Access-Control-Max-Age | Access-Control-Max-Age wird verwendet, um dem Browser mitzuteilen, dass dies möglich ist Vorprüfung Der Zeitpunkt, zu dem das Ergebnis der Anforderungsrückgabe zwischengespeichert wird. Während des Cache-Gültigkeitszeitraums verwendet der Browser die zwischengespeicherten Vorprüfungsergebnisse, um zu bestimmen, ob eine domänenübergreifende Anforderung gesendet werden soll. |
Access-Control-Allow-Methods | Access-Control-Allow-Methods wird verwendet, um dem Browser mitzuteilen, dass er dies kann tatsächlich senden Bei domänenübergreifenden Anforderungen können die unterstützten Anforderungsmethoden eine bestimmte Methodenliste oder ein * (das eine beliebige Methode anzeigt) sein. |
Der Client muss nur den Anforderungsheader gemäß der Spezifikation festlegen.
Der Server erkennt und gibt den entsprechenden Antwortheader gemäß der Spezifikation zurück oder installiert das entsprechende Plug-In, ändert die entsprechende Framework-Konfigurationsdatei usw. Dies hängt von der Sprache und dem Framework ab, die vom Server verwendet werden
SpringBoot CORS-Einstellungsbeispiel
Ein Code über die CORS-Konfiguration in einem Spring Boot Projekt
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
Das Prinzip von JSONP besteht darin, das <script>-Tag in HTML zu verwenden, um Ressourcen domänenübergreifend einzuführen. Erstellen Sie also dynamisch ein <srcipt>-Tag, src ist die Zielschnittstelle + Datenpaket abrufen + Funktionsname für die Datenverarbeitung. Nach dem Empfang der GET-Anfrage analysiert das Backend den Funktionsnamen (Daten) und gibt ihn an das Frontend zurück. Das Frontend<script> führt die Verarbeitungsfunktion dynamisch aus.<br/>Beachten Sie den folgenden Code.</script>
Frontend-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>
Back-End-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 diesem Beispiel sieht die von der Rezeption empfangene Res wie folgt aus
Die Startseite sieht so aus
Hinweis
Da JSONP
Nginx Reverse Proxy realisiert domänenübergreifende
Ideen
Da der Browser Richtlinieneinschränkungen mit gleichem Ursprung hat, setzen wir Das Front-End-Projekt Reicht es nicht aus, die vom Front-End angeforderte API-Schnittstellenadresse unter derselben Quelle zu platzieren? In Kombination mit dem vom Webserver bereitgestellten Reverse-Proxy können domänenübergreifende Probleme ohne Konfiguration im Front-End oder Backend gelöst werden.
Die tatsächliche Hintergrundadresse des Backends: http://xxx.xxx.xxx.xxx:8085
Die Hintergrundadresse des mit Tomcat bereitgestellten Spring Boot-Projekts heißt gsms_test
Nginx-Serveradresse: http://xxx.xxx.xxx.xxx:8082
Sowohl Tomcat als auch Nginx werden mit Docker eingerichtet und die Portweiterleitung erfolgt
Nutzungsbedingungen: Die Entwicklungsumgebung ist ein Linux-System
nginx /etc/nginx/conf.d/default.conf
Der Konfigurationscode lautet wie folgt
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; #} }
Seitenkommunikation unter verschiedenen Domänen und domänenübergreifend
window.name + iframe domänenübergreifend
window.name durchsucht Die von einem Fenster auf dem Server freigegebenen Daten bleiben auch nach dem Laden auf verschiedenen Seiten (oder sogar unter verschiedenen Domänennamen) bestehen (der Wert ändert sich nicht, wenn er nicht geändert wird). , und kann sehr lange unterstützen Namenswert (2 MB). Zum Beispiel Wenn eine Seite in Domäne a Daten von einer Seite in Domäne b erhalten möchte, können Sie den window.name-Wert in Domäne b ändern. Wechseln Sie zu Domäne a und dann wieder zurück, um den window.name-Wert von Domäne b zu erhalten. Aber wir wollen während der Entwicklung auf keinen Fall die Seiten hin- und herwechseln, also müssen wir es mit iframe kombinieren.
Beispiel (implementiert mit thinkjs)
a Der Domänencode lautet wie folgt
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>
b Der Domänencode
nbsp;html> <meta> <title>New ThinkJS Application</title> <h1>server 2</h1> <script> window.name = 'user: xbc'; </script>
Aufgrund der Einschränkung der Same-Origin-Richtlinie erhält die übergeordnete Seite unvollständige Informationen von der domänenübergreifenden Iframe-Seite, nachdem der window.name des Iframes geändert wurde Die B-Domäne muss in eine beliebige Seite unter der A-Domäne konvertiert werden (Window.name darf auf dieser Seite nicht geändert werden) und wird abgerufen.
Da der gegenseitige Zugriff zwischen Iframe und übergeordneter Seite auch durch die Same-Origin-Richtlinie eingeschränkt ist, ist eine Proxy-Seite erforderlich, um domänenübergreifenden Zugriff zu erreichen Zugang.
Ich persönlich halte es für etwas problematisch. Wenn Sie interessiert sind, sehen Sie sich bitte an, wie das Frontend eine Proxy-Seite verwendet das Problem des domänenübergreifenden Iframe-Zugriffs lösen?
Zusammenfassung
Die oben genannten sind alle domänenübergreifende Methoden, die ich verwendet oder getestet habe, und domänenübergreifende Methoden wie postMessage und WebSocket gab es noch nie verwendet. Kontakt ohne Erklärung. Beim Einsatz dieser Methoden in einem Projekt müssen verschiedene Aspekte gezielt berücksichtigt werden
情况 | 方法 |
---|---|
只有GET请求 | JSONP |
对兼容性及浏览器版本无要求 | CORS |
对兼容性及浏览器版本有要求 | iframe 或 服务器反向代理(linux 环境下开发) |
Das obige ist der detaillierte Inhalt vonUltradetaillierte Komplettlösung für domänenübergreifende Probleme (mit Beispielen). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!