Maison > Article > interface Web > La solution la plus complète pour ajax multi-domaines
Quand j'ai commencé à apprendre JavaScript, je ne savais pas ce qu'était l'Ajax inter-domaines, mais j'entendais souvent des grands parler de problèmes inter-domaines Ajax dans tous les domaines, je dois avoir des camarades de classe comme. moi, donc aujourd'hui, nous allons examiner ce qu'est exactement le cross-domain ajax et quelles sont les méthodes pour résoudre le cross-domain ajax !
Avant-propos
Concernant le cross-domain, il existe N types Cet article se concentre uniquement sur les requêtes ajax cross-domain (, ajax cross-. le domaine n'appartient qu'à la navigation. Une partie de la "même politique d'origine" du serveur, d'autres incluent Cookie cross-domain, iframe cross-domain, LocalStorage cross-domain, etc. (non présenté ici), le contenu est à peu près le suivant :
1. Qu'est-ce que c'est ajax cross-domain
Principe
Performance (organisation de quelques problèmes de rencontres et solutions)
2. Comment résoudre ajax cross-domain
Méthode JSONP
Méthode CORS
Méthode de demande de proxy
3.Comment analyser ajax cross-domain
Analyse de capture de paquets http
Quelques exemples
Qu'est-ce que l'ajax cross-domain
Le principe de l'ajax cross-domain
Ajax a un problème d'erreur de requête inter-domaines. La raison principale est due à la navigation. Vous pouvez vous référer à la
Politique de même origine du navigateur et à ses méthodes de contournement
Principe de requête CORS
CORS est une norme du W3C, le nom complet est "Ressource d'origine croisée partage". Il permet au navigateur d'émettre des requêtes XMLHttpRequest vers des serveurs d'origines croisées, surmontant ainsi la limitation selon laquelle AJAX ne peut être utilisé qu'à partir de la même origine.
Fondamentalement, tous les navigateurs actuels ont implémenté la norme CORS. En fait, presque toutes les requêtes ajax des navigateurs sont basées sur le mécanisme CORS, mais les développeurs front-end ne s'en soucient peut-être pas (donc en fait, la solution CORS actuelle principalement). considère comment implémenter l’arrière-plan).
Concernant CORS, il est fortement recommandé de lire
Explication détaillée de CORS pour le partage de ressources entre domaines
Dans De plus, une implémentation est également compilée ici Schéma (version simplifiée) :
Comment déterminer s'il s'agit d'une requête simple ?
Les navigateurs divisent les requêtes CORS en deux catégories : les requêtes simples et les requêtes pas si simples. Tant que les deux conditions suivantes sont remplies en même temps, il s’agit d’une simple demande.
1. La méthode de requête est l'une des trois méthodes suivantes : HEAD, GET, POST
2. Ne dépassez pas les champs suivants :
1. Accepter
Accepter 2. Accepter-Langue
3. Contenu-Langage
4. ID du dernier événement
5. Content-Type (limité à trois valeurs application/x-www-form-urlencoded, multipart/form-data, text/plain)
À chaque fois que différent Si les deux conditions ci-dessus sont remplies, il s’agit d’une demande non simple.
Performances inter-domaines Ajax
Pour être honnête, j'ai compilé un article puis je l'ai utilisé comme solution, mais plus tard j'ai trouvé que c'était encore Beaucoup de gens ne savent toujours pas comment. Nous n'avons pas d'autre choix que de le déboguer, ce qui prend du temps et demande beaucoup de travail. Cependant, même si je l'analyse, je ne jugerai s'il est multi-domaine qu'en fonction des performances correspondantes, c'est donc très important.
Lors d'une requête ajax, s'il y a un phénomène inter-domaines et qu'il n'est pas résolu, le comportement suivant se produira : (Remarque, il s'agit d'une requête ajax. Veuillez ne pas dire pourquoi les requêtes http sont OK mais ajax ne l'est pas, car ajax est accompagné de Cross-domain, donc juste une requête http ok ne fonctionnera pas)
Remarque : veuillez consulter le plan de la question pour la configuration inter-domaine spécifique du back-end.
Le premier phénomène :Aucun en-tête 'Access-Control-Allow-Origin' n'est présent sur la ressource demandée, etLa réponse avait le code d'état HTTP 404
Les raisons de cette situation sont les suivantes :
Cette requête ajax est " Pas une simple requête", donc une requête de contrôle en amont (OPTIONS) sera envoyée avant la requête
2. L'interface d'arrière-plan côté serveur n'autorise pas les requêtes OPTIONS, ce qui entraîne l'impossibilité de trouver l'adresse d'interface correspondante
Solution : Le backend autorise la demande d'options
Deuxième phénomène :Aucun entête 'Access-Control-Allow-Origin' n'est présent sur la ressource demandée, etLe la réponse avait le code d'état HTTP 405
Ce phénomène est différent du premier. Dans ce cas, la méthode en arrière-plan autorise les requêtes OPTIONS, mais certains fichiers de configuration (comme la configuration de sécurité) bloquent les requêtes OPTIONS, ce qui provoque cela.
Solution : Désactivez la configuration de sécurité correspondante sur le backend
Troisième phénomène :Aucun en-tête 'Access-Control-Allow-Origin' n'est présent sur la ressource demandée , Et statut 200
Ce phénomène est différent du premier et du deuxième,Dans dans ce cas, l'arrière-plan côté serveur autorise les requêtes OPTIONS, et l'interface autorise également les requêtes OPTIONS, mais il y a une incohérence lorsque les en-têtes correspondent
Par exemple, la vérification de l'en-tête d'origine ne correspond pas, par exemple, certains Les en-têtes sont manquants (comme l'en-tête commun X-Requested-With), puis le serveur renverra la réponse au front-end Une fois que le front-end aura détecté cela, il déclenchera XHR.onerror, provoquant le front-end. -end console pour signaler une erreur
Solution : Le backend ajoute le support d'en-tête correspondant
Le quatrième phénomène : heade contient plusieurs valeurs '*,*'
Le symptôme est que les informations d'en-tête http de la réponse en arrière-plan comportent deux Access-Control-Allow-Origin : *
Pour être honnête, ce genre de problème se produit. La raison principale est que les personnes qui effectuent une configuration inter-domaines ne comprennent pas le principe, ce qui entraîne des configurations répétées, telles que :
1. Généralement vu dans l'arrière-plan .net (généralement, l'origine est configurée une fois dans web.config, puis à nouveau dans le code Origine ajoutée manuellement une fois (par exemple, le code définit manuellement le retour *))
2. Couramment vu en arrière-plan .net (définir Origin:* dans IIS et la configuration Web du projet en même temps)
Solution (correspondance individuelle) :
1. Il est recommandé de supprimer les * ajoutés manuellement dans le code et d'utiliser uniquement ceux de la configuration du projet
2 , il est recommandé de supprimer la configuration* sous IIS et d'utiliser uniquement celui dans la configuration du projet
Comment résoudre les problèmes multi-domaines Ajax
La solution multi-domaines Ajax générale est résolue via JSONP ou CORS, comme suit : (Notez que JSONP n'est presque plus utilisé, il suffit donc de comprendre JSONP)
Solution JSONP Problèmes inter-domaines
jsonp est une solution relativement ancienne pour résoudre les problèmes inter-domaines (non recommandée en pratique). Voici une brève introduction (si vous souhaitez utiliser JSONP dans des projets réels, vous utiliserez généralement JQ et d'autres bibliothèques de classes qui encapsulent JSONP pour effectuer). ajax)
Principe de mise en œuvre
La raison pour laquelle JSONP peut être utilisé pour résoudre des problèmes inter-domaines Solution, principalement parce que <script> les scripts ont des capacités inter-domaines, et JSONP en profite pour y parvenir. Le principe spécifique est illustré dans la figure </script>
Processus d'implémentation
Les étapes d'implémentation de JSONP sont à peu près les suivantes (voir l'article dans la source)
1 La page Web du client demande JSON au serveur en ajoutant un <. ;script>, cette approche n'est pas limitée par la même politique d'origine
function addScriptTag(src) { var script = document.createElement('script'); script.setAttribute("type","text/javascript"); script.src = src; document.body.appendChild(script); } window.onload = function () { addScriptTag('http://example.com/ip?callback=foo'); } function foo(data) { console.log('response data: ' + JSON.stringify(data)); };
Lors de la demande, l'adresse de l'interface est utilisée comme src de la balise de script construite. est construit, le src final est l'interface Contenu retourné
2. L'interface correspondante du serveur ajoute une couche d'encapsulation de fonction en dehors du paramètre de retour
foo({ "test": "testData" });
3. Le script demandé par le L'élément <script> est exécuté directement en tant que code. À ce stade, tant que le navigateur définit la fonction foo, la fonction sera appelée immédiatement. Les données JSON en tant que paramètres sont traitées comme des <a href="http://www.php.cn/js/js-jsref-tutorial.html" target="_blank">objets JavaScript plutôt que comme des chaînes, évitant ainsi l'étape d'utilisation de JSON.parse. </script>
Notez qu'il existe une différence entre l'interface JSONP générale et les données renvoyées par l'interface ordinaire. Par conséquent, si l'interface doit être compatible JSONO, il faut déterminer s'il existe un paramètre de mot-clé de rappel correspondant. . S'il y en a, il s'agit d'une requête JSONP et les données JSONP sont renvoyées, sinon renvoient des données ordinaires
Notes d'utilisation
Basées sur le principe d'implémentation de JSONP, donc. JSONP ne peut être qu'une requête "GET" et ne peut pas effectuer de requêtes POST ou autres requêtes plus complexes. Ainsi, lorsque vous rencontrez cette situation, vous devez vous référer au CORS suivant pour résoudre les problèmes inter-domaines (il a donc été pratiquement éliminé maintenant)
CORS résout les problèmes inter-domaines
Le principe de CORS a été présenté ci-dessus. Ce qui est principalement présenté ici est la façon dont le backend devrait être. configuré pour résoudre les problèmes dans les projets réels (car un grand nombre de pratiques de projet sont résolues par le backend. Voici quelques solutions backend courantes :
Configuration du backend PHP).
La configuration du backend PHP est presque la plus simple de tous les backends, suivez simplement les étapes ci-dessous :
Étape 1 : Configurez le backend Php pour autoriser le cross-domain
<?php header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept'); //主要为跨域CORS配置的两大基本信息,Origin和headers
Étape 2 : Configurer le serveur Web Apache entre domaines (dans httpd.conf)
Le code d'origine
<Directory /> AllowOverride none Require all denied </Directory>
a été remplacé par le code suivant
<Directory /> Options FollowSymLinks AllowOverride none Order deny,allow Allow from all </Directory>
Configuration en arrière-plan de Node.js (framework express)
Le backend de Node.js est également relativement simple à configurer. Utilisez simplement express pour configurer comme suit :
app.all('*', function(req, res, next) { res.header("Access-Control-Allow-Origin", "*"); res.header("Access-Control-Allow-Headers", "X-Requested-With"); res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS"); res.header("X-Powered-By", ' 3.2.1') //这段仅仅为了方便返回json而已 res.header("Content-Type", "application/json;charset=utf-8"); if(req.method == 'OPTIONS') { //让options请求快速返回 res.sendStatus(200); } else { next(); } });
Configuration en arrière-plan JAVA
La configuration en arrière-plan JAVA doit simplement suivre les étapes suivantes :
Première étape : obtenez le package jar dépendant
Téléchargez cors-filter-1.7.jar, java-property-utils-1.9.jarCes 2. Placez les fichiers de bibliothèque dans le répertoire lib. (Placez-le sous webcontent/WEB-INF/lib/ du projet correspondant)
Étape 2 : Si le projet est construit avec Maven, veuillez ajouter les dépendances suivantes à pom.xml : (Si vous n'êtes pas Maven , veuillez l'ignorer)
<dependency> <groupId>com.thetransactioncompany</groupId> <artifactId>cors-filter</artifactId> <version>[ version ]</version> </dependency>
La version doit être la dernière version stable, CORSFiltre
Étape 3 : Ajouter la configuration CORS au Web.xml du projet ( App/ WEB-INF/web.xml)
<!-- 跨域配置--> <filter> <!-- The CORS filter with parameters --> <filter-name>CORS</filter-name> <filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class> <!-- Note: All parameters are options, if omitted the CORS Filter will fall back to the respective default values. --> <init-param> <param-name>cors.allowGenericHttpRequests</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>cors.allowOrigin</param-name> <param-value>*</param-value> </init-param> <init-param> <param-name>cors.allowSubdomains</param-name> <param-value>false</param-value> </init-param> <init-param> <param-name>cors.supportedMethods</param-name> <param-value>GET, HEAD, POST, OPTIONS</param-value> </init-param> <init-param> <param-name>cors.supportedHeaders</param-name> <param-value>Accept, Origin, X-Requested-With, Content-Type, Last-Modified</param-value> </init-param> <init-param> <param-name>cors.exposedHeaders</param-name> <!--这里可以添加一些自己的暴露Headers --> <param-value>X-Test-1, X-Test-2</param-value> </init-param> <init-param> <param-name>cors.supportsCredentials</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>cors.maxAge</param-name> <param-value>3600</param-value> </init-param> </filter> <filter-mapping> <!-- CORS Filter mapping --> <filter-name>CORS</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
Veuillez noter que le fichier de configuration ci-dessus doit être placé devant web.xml et exister en tant que premier filtre (il peut y avoir plusieurs filtres)
Étape 4 : Erreurs possibles de configuration du module de sécurité (notez que certains frameworks, tels que les frameworks privés d'entreprise, ont des modules de sécurité. Parfois, ces configurations de modules de sécurité affecteront la configuration inter-domaines. Dans ce cas, vous pouvez essayer de les activer désactivé en premier)
Configuration JAVA Spring Boot
20171230 supplémentaire
Répertorier uniquement les configurations globales simples
@Configuration public class CorsConfig { private CorsConfiguration buildConfig() { CorsConfiguration corsConfiguration = new CorsConfiguration(); // 可以自行筛选 corsConfiguration.addAllowedOrigin("*"); corsConfiguration.addAllowedHeader("*"); corsConfiguration.addAllowedMethod("*"); return corsConfiguration; } @Bean public CorsFilter corsFilter() { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", buildConfig()); return new CorsFilter(source); } }
Créez une nouvelle configuration, puis ajoutez l'annotation Configuration pour configurer avec succès
PS : Cette partie de la méthode est incluse et n'a pas été pratiquée personnellement, mais sur la base des retours, elle est théoriquement faisable
Configuration en arrière-plan NET
La configuration en arrière-plan .NET peut faire référence aux étapes suivantes :
Étape 1 : Configuration du site Web
Ouvrez le Panneau de configuration, sélectionnez Outils de gestion, sélectionnez IIS ; cliquez avec le bouton droit sur votre site Web et sélectionnez Parcourir ; ouvrez le répertoire où se trouve le site Web, utilisez le Bloc-notes pour ouvrir le fichier web.config et ajoutez le fichier web.config. suite aux informations de configuration, redémarrez le site
请注意,以上截图较老,如果配置仍然出问题,可以考虑增加更多的headers允许,比如:
"Access-Control-Allow-Headers":"X-Requested-With,Content-Type,Accept,Origin"
第二步:其它更多配置,如果第一步进行了后,仍然有跨域问题,可能是:
1、接口中有限制死一些请求类型(比如写死了POST等),这时候请去除限 制
2、接口中,重复配置了Origin:*,请去除即可
3、IIS服务器中,重复配置了Origin:*,请去除即可
代理请求方式解决接口跨域问题
注意,由于接口代理是有代价的,所以这个仅是开发过程中进行的。
与前面的方法不同,前面CORS是后端解决,而这个主要是前端对接口进行代理,也就是:
1、前端ajax请求的是本地接口
2、本地接口接收到请求后向实际的接口请求数据,然后再将信息返回给前端
3、一般用node.js即可代理
关于如何实现代理,这里就不重点描述了,方法和多,也不难,基本都是基于node.js的。
搜索关键字node.js,代理请求即可找到一大票的方案。
OPTIONS预检的优化
Access-Control-Max-Age:
这个头部加上后,可以缓存此次请求的秒数。
在这个时间范围内,所有同类型的请求都将不再发送预检请求而是直接使用此次返回的头作为判断依据。
非常有用,可以大幅优化请求次数
如何分析ajax跨域
上述已经介绍了跨域的原理以及如何解决,但实际过程中,发现仍然有很多人对照着类似的文档无法解决跨域问题,主要体现在,前端人员不知道什么时候是跨域问题造成的,什么时候不是,因此这里稍微介绍下如何分析一个请求是否跨域:
抓包请求数据
第一步当然是得知道我们的ajax请求发送了什么数据,接收了什么,做到这一步并不难,也不需要fiddler等工具,仅基于Chrome即可
1、Chrome浏览器打开对应发生ajax的页面,F12打开Dev Tools
2、发送ajax请求
3、右侧面板->NetWork->XHR,然后找到刚才的ajax请求,点进去
示例一(正常的ajax请求)
上述请求是一个正确的请求,为了方便,我把每一个头域的意思都表明了,我们可以清晰的看到,接口返回的响应头域中,包括了
Access-Control-Allow-Headers: X-Requested-With,Content-Type,Accept Access-Control-Allow-Methods: Get,Post,Put,OPTIONS Access-Control-Allow-Origin: *
所以浏览器接收到响应时,判断的是正确的请求,自然不会报错,成功的拿到了响应数据。
示例二(跨域错误的ajax请求)
为了方便,我们仍然拿上面的错误表现示例举例。
这个请求中,接口Allow里面没有包括OPTIONS,所以请求出现了跨域、
这个请求中,Access-Control-Allow-Origin: *出现了两次,导致了跨域配置没有正确配置,出现了错误。
更多跨域错误基本都是类似的,就是以上三样没有满足(Headers,Allow,Origin),这里不再一一赘述。
示例三(与跨域无关的ajax请求)
当然,也并不是所有的ajax请求错误都与跨域有关,所以请不要混淆,比如以下:
更多
基本上都是这样去分析一个ajax请求,通过Chrome就可以知道了发送了什么数据,收到了什么数据,然后再一一比对就知道问题何在了。
总结
跨域是一个老生常谈的话题,网上也有大量跨域的资料,并且有不少精品(比如阮一峰前辈的),但是身为一个前端人员不应该浅尝而止,故而才有了本文。
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!