Cet article présente principalement le framework Koa2 pour utiliser CORS pour compléter des requêtes ajax inter-domaines. Maintenant, je le partage avec vous et vous donne une référence.
Il existe de nombreuses façons d'implémenter des requêtes ajax inter-domaines, dont l'une consiste à utiliser CORS, et la clé de cette méthode est de la configurer côté serveur.
Cet article explique uniquement la configuration la plus basique qui peut compléter une réponse ajax inter-domaines normale (je ne sais pas comment faire une configuration approfondie).
CORS divise les requêtes en requêtes simples et requêtes non simples. On peut simplement penser que les requêtes simples sont des requêtes d'obtention et de publication sans en-têtes de requête supplémentaires, et s'il s'agit d'une requête de publication, le format de la requête ne peut pas être une application. /json (car je n'ai pas une compréhension approfondie de ce domaine. S'il y a une erreur, j'espère que quelqu'un pourra signaler l'erreur et suggérer des modifications). Le reste, les requêtes put et post, les requêtes avec Content-Type application/json et les requêtes avec des en-têtes de requête personnalisés sont des requêtes non simples.
La configuration d'une requête simple est très simple. Si vous avez seulement besoin de compléter la réponse pour atteindre l'objectif, il vous suffit de configurer Access-Control-Allow-Origin dans l'en-tête de réponse.
Si nous voulons accéder au nom de domaine http://127.0.0.1:3001 sous le nom de domaine http://localhost:3000. Vous pouvez effectuer la configuration suivante :
app.use(async (ctx, next) => { ctx.set('Access-Control-Allow-Origin', 'http://localhost:3000'); await next(); });
Utilisez ensuite ajax pour lancer une requête simple, telle qu'une demande de publication, et vous pourrez facilement obtenir la réponse correcte du serveur.
Le code expérimental est le suivant :
$.ajax({ type: 'post', url: 'http://127.0.0.1:3001/async-post' }).done(data => { console.log(data); })
Code côté serveur :
router.post('/async-post',async ctx => { ctx.body = { code: "1", msg: "succ" } });
Ensuite, vous pouvez obtenir les informations de réponse correctes.
Si vous regardez les informations d'en-tête de la requête et de la réponse à ce moment-là, vous constaterez que l'en-tête de la requête a une origine supplémentaire (il existe également un référent pour l'adresse URL de la requête), et le l’en-tête de réponse a un Access-Control-Allow-Origin supplémentaire.
Vous pouvez désormais envoyer des requêtes simples, mais vous avez toujours besoin d'une autre configuration pour envoyer des requêtes non simples.
Lorsqu'une requête non simple est émise pour la première fois, deux requêtes seront en fait émises. La première est une requête de contrôle en amont. La méthode de requête de cette requête est OPTIONS. la demande est transmise. Indique si le type de demande non simple peut recevoir une réponse réussie.
Afin de faire correspondre cette requête de type OPTIONS sur le serveur, vous devez créer un middleware pour la faire correspondre et donner une réponse afin que cette pré-vérification puisse réussir.
app.use(async (ctx, next) => { if (ctx.method === 'OPTIONS') { ctx.body = ''; } await next(); });
De cette façon, la demande OPTIONS peut passer.
Si vous vérifiez l'en-tête de la demande de contrôle en amont, vous constaterez qu'il y a deux autres en-têtes de demande.
Access-Control-Request-Method: PUT Origin: http://localhost:3000
Négociez avec le serveur via ces deux informations d'en-tête pour voir si les conditions de réponse du serveur sont remplies.
C'est facile à comprendre. Puisque l'en-tête de requête contient deux informations supplémentaires, l'en-tête de réponse doit naturellement avoir deux informations correspondantes. Les deux informations sont les suivantes :
Access-Control-Allow-Origin: http://localhost:3000 Access-Control-Allow-Methods: PUT,DELETE,POST,GET
Access-Control-Allow-Origin: http://localhost:3000 Access-Control-Allow-Methods: PUT,DELETE,POST,GET
Origin: http://localhost:3000
$.ajax({ type: 'put', url: 'http://127.0.0.1:3001/put' }).done(data => { console.log(data); });
app.use(async (ctx, next) => { ctx.set('Access-Control-Allow-Origin', 'http://localhost:3000'); ctx.set('Access-Control-Allow-Methods', 'PUT,DELETE,POST,GET'); await next(); });
Access-Control-Max-Age: 86400
app.use(async (ctx, next) => { ctx.set('Access-Control-Allow-Origin', 'http://localhost:3000'); ctx.set('Access-Control-Allow-Methods', 'PUT,DELETE,POST,GET'); ctx.set('Access-Control-Max-Age', 3600 * 24); await next(); });
$.ajax({ type: 'put', url: 'http://127.0.0.1:3001/put', data: { name: '黄天浩', age: 20 }, xhrFields: { withCredentials: true } }).done(data => { console.log(data); });
app.use(async (ctx, next) => { ctx.set('Access-Control-Allow-Origin', 'http://localhost:3000'); ctx.set('Access-Control-Allow-Methods', 'PUT,DELETE,POST,GET'); ctx.set('Access-Control-Allow-Credentials', true); await next(); });
这时就可以带着cookie到服务器了,并且服务器也可以对cookie进行改动。但是cookie仍是http://127.0.0.1:3001域名下的cookie,无论怎么操作都在该域名下,无法访问其他域名下的cookie。
现在为止CORS的基本功能已经都提到过了。
一开始我不知道怎么给Access-Control-Allow-Origin,后来经人提醒,发现可以写一个白名单数组,然后每次接到请求时判断origin是否在白名单数组中,然后动态的设置Access-Control-Allow-Origin,代码如下:
app.use(async (ctx, next) => { if (ctx.request.header.origin !== ctx.origin && whiteList.includes(ctx.request.header.origin)) { ctx.set('Access-Control-Allow-Origin', ctx.request.header.origin); ctx.set('Access-Control-Allow-Methods', 'PUT,DELETE,POST,GET'); ctx.set('Access-Control-Allow-Credentials', true); ctx.set('Access-Control-Max-Age', 3600 * 24); } await next(); });
这样就可以不用*通配符也可匹配多个origin了。
注意:ctx.origin与ctx.request.header.origin不同,ctx.origin是本服务器的域名,ctx.request.header.origin是发送请求的请求头部的origin,二者不要混淆。
最后,我们再稍微调整一下自定义的中间件的结构,防止每次请求都返回Access-Control-Allow-Methods以及Access-Control-Max-Age,这两个响应头其实是没有必要每次都返回的,只是第一次有预检的时候返回就可以了。
调整后顺序如下:
app.use(async (ctx, next) => { if (ctx.request.header.origin !== ctx.origin && whiteList.includes(ctx.request.header.origin)) { ctx.set('Access-Control-Allow-Origin', ctx.request.header.origin); ctx.set('Access-Control-Allow-Credentials', true); } await next(); }); app.use(async (ctx, next) => { if (ctx.method === 'OPTIONS') { ctx.set('Access-Control-Allow-Methods', 'PUT,DELETE,POST,GET'); ctx.set('Access-Control-Max-Age', 3600 * 24); ctx.body = ''; } await next(); });
这样就减少了多余的响应头。
上面是我整理给大家的,希望今后会对大家有帮助。
相关文章:
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!