Maison  >  Article  >  Opération et maintenance  >  Comment résoudre les problèmes cross-domaines ? Une brève analyse des solutions courantes

Comment résoudre les problèmes cross-domaines ? Une brève analyse des solutions courantes

青灯夜游
青灯夜游avant
2023-04-25 19:57:582002parcourir

Comment résoudre les problèmes cross-domaines ? Une brève analyse des solutions courantes

Le cross-domain est un scénario souvent rencontré en développement, et c'est aussi une question souvent évoquée en entretien. La maîtrise des solutions inter-domaines communes et des principes qui les sous-tendent peut non seulement améliorer notre efficacité de développement, mais également nous rendre plus à l'aise lors des entretiens.

Alors, parlons aujourd'hui de plusieurs façons courantes de résoudre les problèmes inter-domaines du point de vue du front-end.

Qu'est-ce que le cross-domain

Avant de parler de cross-domain, jetons d'abord un coup d'œil à la composition d'une URL :

La composition d'une URL comprend généralement le protocole, le nom d'hôte, le numéro de port, le chemin , paramètres de requête et ancres Plusieurs parties.

Un exemple d'URL est présenté ici :

https://www.example.com:8080/path/resource.html?page=1&sort=desc#header

Dans l'exemple ci-dessus :
gird Le protocole est HTTPS
g Le nom d'hôte est www.example.com
g Le numéro de port est 8080
g Le chemin est /path /resource.html
● Le paramètre de requête est page=1&sort=desc
Quantity L'ancre est header

Ce qu'on appelle le cross-domain signifie que toute partie du protocole, du nom d'hôte et du numéro de port dans l'URL de la requête est différent.

En prenant l'URL ci-dessus comme exemple, les méthodes d'écriture suivantes sont considérées comme étant inter-domaines :

http://www.example.com:8080/    // 协议不同
https://www.example.a.com:8080/ // 主机名不同
https://www.example.com:8081/   // 端口号不同

Pourquoi est-ce inter-domaine

En faitl'apparition de problèmes inter-domaines est limitée par la politique de même origine du navigateur.

所谓同源策略,其实是浏览器的一种安全机制,用于限制一个网页中的网络请求仅能够访问来自同一源(域名、协议和端口号均相同)的资源,主要目的是防止恶意网站通过脚本窃取其他网站的敏感数据,保障用户的隐私和安全。

Lorsque des scripts côté navigateur (fichiers js) accèdent aux ressources réseau d'autres domaines, des problèmes inter-domaines se produiront.

Comment résoudre les problèmes inter-domaines

Comme mentionné précédemment, l'apparition de problèmes inter-domaines est limitée par la politique de même origine du navigateur, de sorte que les solutions courantes pour résoudre les problèmes inter-domaines tournent en fait autour des navigateurs. :

1. Serveur proxy

Dans notre développement habituel, la solution la plus couramment utilisée pour résoudre les problèmes inter-domaines est d'utiliser un serveur proxy.

Serveur proxyPour résoudre le problème inter-domaines, il capture en fait la fonctionnalité selon laquelle la politique de même origine n'est limitée que par l'accès du navigateur au serveur, et il n'y a aucune restriction sur l'accès du serveur au serveur . En tant que serveur intermédiaire, il dispose d'une fonction de transfert de requêtes.

Plus précisément, la page Web écrite par l'ingénieur front-end s'exécute sur un serveur proxy construit par un échafaudage tel que webpack. Lorsque la page Web frontale initie une requête réseau dans le navigateur, la requête est en fait envoyée au serveur proxy. , puis le serveur proxy La demande sera transmise au serveur cible, puis la réponse renvoyée par le serveur cible sera transmise au client.

Le serveur proxy joue un rôle de relais dans ce processus et peut modifier, filtrer et intercepter les requêtes et réponses pour réaliser certaines fonctions spécifiques. Étant donné que la page Web frontale s'exécute sur le serveur proxy, il n'y a pas de problème entre domaines.

Alors, comment le serveur proxy transmet-il les requêtes dans l'environnement en ligne et l'environnement de développement ?

1. Environnement en ligne

Dans l'environnement en ligne, nous utilisons généralement nginx comme proxy inverse pour transmettre la requête frontale à l'interface cible.

nginx est un serveur Web léger à haute concurrence, piloté par événements, multiplateforme et peut être configuré à la fois sur Windows et Linux.

La principale méthode qu'il utilise en tant que serveur proxy pour résoudre les problèmes inter-domaines en cours de développement consiste à écouter le port en cours d'exécution de l'URL frontale en ligne, puis à transmettre la requête après avoir rencontré une requête contenant une balise spéciale.

2. Environnement de développement

Dans l'environnement de développement, qu'il s'agisse d'un projet front-end construit à l'aide de webpack ou de vite ou d'un autre échafaudage, l'essentiel de la résolution des problèmes inter-domaines est réalisé avec l'aide de http-proxy-middleware middleware . Le cœur du middleware http-proxy-middleware est une autre encapsulation de http-proxy.

Voici un exemple de code qui utilise http-proxy-middleware pour implémenter la fonction de transfert de requêtes dans le projet :

const { createProxyMiddleware } = require('http-proxy-middleware');

module.exports = {
  server: {
    proxy: {
      // 将 /api/* 的请求代理到 http://localhost:3000/*
      '/api': {
        target: 'http://localhost:3000',
        changeOrigin: true,
        pathRewrite: { '^/api': '/' }
      }
    }
  }
};

Ensuitenous pouvons utiliser le nœud natif nous-mêmes et utiliser la bibliothèque http-proxy pour créer un transfert de requête fonction Démo du serveur proxy, les amis intéressés peuvent tester et jouer par eux-mêmes  :

1. Tout d'abord, vous devez créer un dossier vide (nommé en anglais) comme dossier du projet, puis utiliser le npm init -y commande pour installer le projet Projet mis à niveau vers le nœud :

npm init -y

2. Créez ensuite un fichier index.html dans le répertoire racine du projet pour lancer des requêtes inter-domaines :

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>请求转发测试</title>
</head>

<body>
    <h1>请求转发测试</h1>
    <p id="message"></p>
    <script>
        fetch(&#39;/api/login&#39;)
            .then(response => response.text())
            .then(data => {
                document.getElementById(&#39;message&#39;).textContent = data;
            });
    </script>
</body>

</html>

3. Créez ensuite un nouveau index dans le répertoire racine du projet fichier .js pour écrire du code côté serveur.
Le fichier index.js est le fichier principal pour implémenter un serveur proxy avec fonction de transfert de requêtes.

const http = require(&#39;http&#39;);
const httpProxy = require(&#39;http-proxy&#39;);
const fs = require(&#39;fs&#39;);
const path = require(&#39;path&#39;);

// 创建代理服务器实例
const proxy = httpProxy.createProxyServer({});

// 创建HTTP服务器
const server = http.createServer((req, res) => {
    if (req.url === &#39;/&#39; || req.url.endsWith(&#39;.html&#39;)) {
        // 读取HTML文件
        const filename = path.join(__dirname, &#39;index.html&#39;);
        fs.readFile(filename, &#39;utf8&#39;, (err, data) => {
            if (err) {
                res.writeHead(500);
                res.end(&#39;Error reading HTML file&#39;);
            } else {
                res.writeHead(200, { &#39;Content-Type&#39;: &#39;text/html&#39; });
                res.end(data);
            }
        });
    } else if (req.url.startsWith(&#39;/api&#39;)) {
        // 重写路径,替换跨域关键词
        req.url = req.url.replace(/^\/api/, &#39;&#39;);
        // 将请求转发至目标服务器
        proxy.web(req, res, {
            target: &#39;http://localhost:3000/&#39;,
            changeOrigin: true,
        });    
    }
});

// 监听端口
server.listen(8080, () => {
    console.log(&#39;Server started on port 8080&#39;);
});

4. Ensuite, écrivez le contenu du fichiertarget.js du serveur cible pour tester l'accès inter-domaines :

const http = require(&#39;http&#39;);

const server = http.createServer((req, res) => {
    if (req.url.startsWith(&#39;/login&#39;)) {
        res.writeHead(200, { &#39;Content-Type&#39;: &#39;text/plain&#39; });
        res.end(&#39;我是localhost主机3000端口下的方法,恭喜你访问成功!&#39;);
    } else {
        res.writeHead(200, { &#39;Content-Type&#39;: &#39;text/plain&#39; });
        res.end(&#39;Hello, world!&#39;);
    }
});

server.listen(3000, () => {
    console.log(&#39;Target server is listening on port:3000&#39;);
})

5. 打开终端,输入启动目标服务器的命令:

node ./target.js //项目根目录下执行

6. 再开一个终端启动代理服务器,等待浏览器端发起请求就可以啦:

node ./index.js //项目根目录下执行

7. 最后在浏览器里访问http://localhost:8080, 打开控制台即可查看效果:

可以发现,浏览器network模块的网络请求确实是访问的8080端口的方法,但是我们的服务器默默的做了请求转发的功能,并将请求转发获取到的内容返回到了前端页面上。

其实http-proxy是对node内置库http的进一步封装,网络请求的核心部分还是使用http创建一个服务器对象去访问的。感兴趣的同学可以再读读http-proxy的源码~

除了代理服务器这种绕过浏览器同源策略的解决方式外,从前端的角度解决跨域问题还有如下一些常见的方法:

1.借助JSONP

JSONP的原理是通过动态创建3f1c4e4b6b16bbbd69b2ee476dc4f83a标签,向服务器发送请求并在请求URL中传递一个回调函数名(通常是在本地定义的函数名),服务器在返回的数据中将这个回调函数名和实际数据一起封装成一个JavaScript函数的调用,返回给客户端,客户端利用该回调函数对数据进行处理。

JSONP之所以能够跨域请求数据,是因为浏览器对于3f1c4e4b6b16bbbd69b2ee476dc4f83a标签的请求不会受到同源策略的限制。

需要注意的是,使用JSONP技术的前提是服务器需要支持JSONP的方式,即在返回的数据中包含回调函数名和实际数据的封装,否则客户端无法处理返回的数据。

此外,JSONP只支持GET请求,不支持POST等其他HTTP请求方式,因为3f1c4e4b6b16bbbd69b2ee476dc4f83a标签只支持GET请求。

因此JSONP这种方式在我们的开发中使用的场景不多。

2.使用CORS

CORS全称为Cross-Origin Resource Sharing,它通过HTTP头部信息告诉浏览器哪些跨域请求是被允许的,从而实现安全的跨域访问。

CORS解决跨域需要浏览器端和服务器端的配合。原理是在服务器端设置HTTP头部信息,告诉浏览器允许哪些源(域名、协议、端口)访问服务器上的资源,如果请求的源不在允许的列表中,则浏览器将拒绝访
问。

服务器可以通过设置Access-Control-Allow-OriginAccess-Control-Allow-HeadersAccess-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

Il convient de noter que la condition préalable à l'utilisation de CORS est que le serveur doit définir des informations d'en-tête HTTP pertinentes et que le navigateur prend en charge CORS. De plus, CORS ne prend en charge que les navigateurs modernes, et certains navigateurs plus anciens peuvent ne pas prendre en charge CORS.

3. D'autres solutions

telles que WebSocket, postMessage, etc.

Résumé

Ces dernières années, avec le développement rapide de la technologie front-end et back-end, indépendante le développement du front-end et du back-end est progressivement devenu un modèle de développement courant. Les programmeurs front-end et back-end n'ont qu'à se mettre d'accord sur l'interface, puis développer les modules correspondants indépendamment et enfin effectuer un débogage conjoint de l'interface. Pendant le processus de débogage commun de l'interface, le développement interdomaine dans l'environnement de développement est un problème qui doit être résolu.

De plus, une fois le projet back-end actuel emballé et déplacé vers le cloud, lorsque la page front-end accède à l'interface back-end via l'adresse en ligne, Le cross-domain dans l'environnement en ligne est également un problème cela doit être résolu.

Cet article décrit plusieurs solutions inter-domaines courantes. Chacune de ces solutions a ses propres avantages et inconvénients. Vous pouvez choisir une solution adaptée en fonction de la situation réelle pour résoudre les problèmes inter-domaines correspondants~

Tutoriel recommandé : tutoriel nginx

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer