Heim  >  Artikel  >  Web-Frontend  >  Ultradetaillierte Komplettlösung für domänenübergreifende Probleme (mit Beispielen)

Ultradetaillierte Komplettlösung für domänenübergreifende Probleme (mit Beispielen)

不言
不言nach vorne
2019-01-14 10:05:472522Durchsuche

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
请求头 解释
Origin Origin头在跨域请求或预先请求中,标明发起跨域请求的源域名。
Access-Control-Request-Method Access-Control-Request-Method头用于表明跨域请求使用的实际HTTP方法
Access-Control-Request-Headers Access-Control-Request-Headers用于在预先请求时,告知服务器要发起的跨域请求中会携带的请求头信息
Origin

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-Allow-Origin Access-Control-Allow-Origin头中携带了服务器端验证后的允许的跨域请求域名,可以是一个具体的域名或是一个*(表示任意域名)。
Access-Control-Expose-Headers Access-Control-Expose-Headers头用于允许返回给跨域请求的响应头列表,在列表中的响应头的内容,才可以被浏览器访问。
Access-Control-Max-Age Access-Control-Max-Age用于告知浏览器可以将预先检查请求返回结果缓存的时间,在缓存有效期内,浏览器会使用缓存的预先检查结果判断是否发送跨域请求。
Access-Control-Allow-Methods Access-Control-Allow-Methods用于告知浏览器可以在实际发送跨域请求时,可以支持的请求方法,可以是一个具体的方法列表或是一个*(表示任意方法)。
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
Die Antwort Der Header enthält hauptsächlich
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.

So verwenden Sie

  • 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(&#39;script&#39;);
    script.type = &#39;text/javascript&#39;;

    // 传参并指定回调执行函数为getData
    script.src = &#39;http://localhost:8080/users?username=xbc&callback=handleData&#39;;
    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

Ultradetaillierte Komplettlösung für domänenübergreifende Probleme (mit Beispielen)

Die Startseite sieht so aus

Ultradetaillierte Komplettlösung für domänenübergreifende Probleme (mit Beispielen)

Hinweis

Da JSONP verwendet, kann es nur GET-Anfragen unterstützen. Andere Anforderungen können nicht implementiert werden

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.

Nehmen Sie Nginx als Beispiel

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.confDer 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(&#39;proxy&#39;);
        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 = &#39;http://127.0.0.1:8360/sub.html&#39; 
    }
</script>
<iframe>        </iframe>

b Der Domänencode

nbsp;html>


<meta>
<title>New ThinkJS Application</title>


  <h1>server 2</h1>
<script>
  window.name = &#39;user: xbc&#39;;
</script>

Hinweis

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.

Proxy-Seite + Iframe, um domänenübergreifenden Zugriff zu erreichen

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.

Ultradetaillierte Komplettlösung für domänenübergreifende Probleme (mit Beispielen)

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!

Stellungnahme:
Dieser Artikel ist reproduziert unter:segmentfault.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen