CORS ، تقاسم الموارد عبر الأصول

مقدمة لمشاركة الموارد عبر المنشأ ، طريقة للسماح للعملاء والخوادم بالتواصل حتى لو لم يكونوا على نفس المجال

عادةً ما يمكن لتطبيق JavaScript قيد التشغيل في المستعرض الوصول فقط إلى موارد HTTP على نفس المجال (الأصل) الذي يخدمه.

يعمل تحميل الصور أو البرامج النصية / الأنماط دائمًا ، ولكنXHRوأحضرستفشل المكالمات إلى خادم آخر ، ما لم ينفذ هذا الخادم طريقة للسماح بهذا الاتصال.

هذه الطريقة تسمى CORS ،تبادل الموارد عبر المنشأ.

أيضا تحميل خطوط الويب باستخدام@font-faceسياسة نفس الأصل بشكل افتراضي وأشياء أخرى أقل شيوعًا (مثل زخارف WebGL وdrawImageالموارد التي تم تحميلها في Canvas API).

أحد الأشياء المهمة جدًا التي تحتاج إلى CORS هووحدات ES، تم طرحه مؤخرًا في المتصفحات الحديثة.

إذا لم تقم بإعداد سياسة CORSعلى الخادمالذي يسمح بخدمة أصول الطرف الثالث ، فسيفشل الطلب.

مثال على الجلب:

Fetch failed because of CORS policy

مثال XHR:

XHR request failed because of CORS policy

يفشل مورد متعدد الأصول إذا كان:

  • إلى مختلفنطاق
  • إلى مختلفالمجال الفرعي
  • إلى مختلفميناء
  • إلى مختلفبروتوكول

وهو موجود لأمانك ، لمنع المستخدمين الضارين من استغلالمنصة الويب.

ولكن إذا كنت تتحكم في كل من الخادم والعميل ، فلديك كل الأسباب الوجيهة للسماح لهما بالتحدث مع بعضهما البعض.

كيف؟

يعتمد ذلك على مكدس جانب الخادم الخاص بك.

دعم المتصفح

جيد جدًا (الكل بشكل أساسي باستثناء IE <10):

CORS browser support

مثال مع Express

إذا كنت تستخدم Node.js و Express كإطار عمل ، فاستخدم ملحقحزمة البرامج الوسيطة CORS.

إليك تنفيذ بسيط لـ ExpressNode.jsالخادم:

const express = require('express')
const app = express()

app.get(’/without-cors’, (req, res, next) => { res.json({ msg: ‘😞 no CORS, no party!’ }) })

const server = app.listen(3000, () => { console.log(‘Listening on port %s’, server.address().port) })

إذا ضربت/without-corsمع طلب جلب من أصل مختلف ، فسيؤدي ذلك إلى إثارة مشكلة CORS.

كل ما عليك القيام به لجعل الأمور تسير على ما يرام هو أن تطلبcorsالحزمة المرتبطة أعلاه ، وقم بتمريرها كوظيفة وسيطة إلى معالج طلب نقطة النهاية:

const express = require('express')
const cors = require('cors')
const app = express()

app.get(’/with-cors’, cors(), (req, res, next) => { res.json({ msg: ‘WHOAH with CORS it works! 🔝 🎉’ }) })

/* the rest of the app */

لقد قدمت مثالًا بسيطًا لـ Glitch ، إليك رمزه:https://glitch.com/edit/#!/flavio-cors-client.

هذا هو خادم Node.js Express:https://glitch.com/edit/#!/flaviocopes-cors-example-express

لاحظ كيف أن الطلب الذي فشل لأنه لا يتعامل مع عناوين CORS بشكل صحيح لا يزال مستلمًا ، كما ترى في لوحة الشبكة ، حيث تجد الرسالة التي أرسلها الخادم:

No response from CORS

السماح بأصول محددة فقط

ومع ذلك ، فإن هذا المثال به مشكلة: سيتم قبول أي طلب من قبل الخادم باعتباره أصل مشترك.

كما ترى في لوحة الشبكة ، فإن الطلب الذي تم تمريره له رأس استجابةaccess-control-allow-origin: *:

The CORS response header

تحتاج إلى تكوين الخادم للسماح لمصدر واحد فقط بالخدمة ، وحظر كل الآخرين.

باستخدام نفس الشيءcorsمكتبة العقدة ، وإليك كيفية القيام بذلك:

const cors = require('cors')

const corsOptions = { origin: https://yourdomain.com, }

app.get(’/products/:id’, cors(corsOptions), (req, res, next) => { //… })

يمكنك تقديم المزيد أيضًا:

const whitelist = ['http://example1.com', 'http://example2.com']
const corsOptions = {
  origin: function (origin, callback) {
    if (whitelist.indexOf(origin) !== -1) {
      callback(null, true)
    } else {
      callback(new Error('Not allowed by CORS'))
    }
  },
}

الاختبار المبدئي

هناك بعض الطلبات التي يتم التعامل معها بطريقة "بسيطة". الجميعGETالطلبات تنتمي إلى هذه المجموعة.

أيضابعض POSTوHEADالطلبات تفعل كذلك.

POSTالطلبات موجودة أيضًا في هذه المجموعة ، إذا كانت تفي بمتطلبات استخدام نوع المحتوى

  • application/x-www-form-urlencoded
  • multipart/form-data
  • text/plain

يجب أن تمر جميع الطلبات الأخرى خلال مرحلة الموافقة المسبقة ، والتي تسمى الاختبار المبدئي. يقوم المستعرض بذلك لتحديد ما إذا كان لديه الإذن بتنفيذ إجراء ما ، عن طريق إصدار ملفOPTIONSطلب.

يحتوي طلب الاختبار المبدئي على عدد قليل من الرؤوس التي سيستخدمها الخادم للتحقق من الأذونات (تم حذف الحقول غير ذات الصلة):

OPTIONS /the/resource/you/request
Access-Control-Request-Method: POST
Access-Control-Request-Headers: origin, x-requested-with, accept
Origin: https://your-origin.com

The server will respond with something like this(irrelevant fields omitted):

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://your-origin.com
Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE

We checked for POST, but the server tells us we can also issue other HTTP request types for that particular resource.

Following the Node.js Express example above, the server must also handle the OPTIONS request:

var express = require('express')
var cors = require('cors')
var app = express()

//allow OPTIONS on just one resource app.options(’/the/resource/you/request’, cors())

//allow OPTIONS on all resources app.options(’*’, cors())


More browser tutorials: