اكشف أسرار سياسة CORS (مشاركة الموارد عبر المصادر) وتعلم كيفية تمكين الطلبات عبر النطاقات بأمان في تطبيقات الويب الخاصة بك. يغطي هذا الدليل الشامل كل شيء من الأساسيات إلى الإعدادات المتقدمة.
إزالة الغموض عن سياسة CORS: دليل شامل لمشاركة الموارد عبر المصادر
في عالم الويب المترابط اليوم، تحتاج التطبيقات بشكل متكرر إلى الوصول إلى موارد من مصادر مختلفة. وهنا يأتي دور مشاركة الموارد عبر المصادر (CORS). تعد CORS آلية أمان حاسمة تحكم كيفية تعامل متصفحات الويب مع الطلبات من مصدر واحد (نطاق وبروتوكول ومنفذ) إلى مصدر مختلف. إن فهم CORS ضروري لكل مطور ويب لبناء تطبيقات ويب آمنة وفعالة.
ما هي سياسة المصدر الواحد؟
قبل الخوض في تفاصيل CORS، من المهم فهم سياسة المصدر الواحد (SOP). تعد SOP آلية أمان أساسية يتم تطبيقها في متصفحات الويب. والغرض منها هو منع النصوص البرمجية الخبيثة على موقع ويب من الوصول إلى البيانات الحساسة على موقع ويب آخر. يتم تعريف المصدر من خلال مجموعة من البروتوكول (مثل HTTP أو HTTPS)، والنطاق (مثل example.com)، ورقم المنفذ (مثل 80 أو 443). يعتبر عنوانا URL من نفس المصدر إذا كانا يشتركان في نفس البروتوكول والنطاق والمنفذ.
مثال:
http://example.com/app1
وhttp://example.com/app2
- نفس المصدر (نفس البروتوكول والنطاق والمنفذ)https://example.com/app1
وhttp://example.com/app1
- مصدر مختلف (بروتوكول مختلف)http://example.com:8080/app1
وhttp://example.com/app1
- مصدر مختلف (منفذ مختلف)http://sub.example.com/app1
وhttp://example.com/app1
- مصدر مختلف (نطاق فرعي مختلف – يعتبر نطاقًا مختلفًا)
تقيد سياسة المصدر الواحد (SOP) النصوص البرمجية من الوصول إلى الموارد من مصدر مختلف ما لم يتم اتخاذ تدابير محددة، مثل CORS، للسماح بذلك.
لماذا تُعد سياسة CORS ضرورية؟
بينما تعد سياسة المصدر الواحد حيوية للأمان، إلا أنها يمكن أن تكون مقيدة أيضًا. تعتمد العديد من تطبيقات الويب الحديثة على جلب البيانات من خوادم مختلفة، مثل واجهات برمجة التطبيقات (APIs) أو شبكات توصيل المحتوى (CDNs). توفر CORS طريقة محكومة لتخفيف قيود SOP والسماح بالطلبات المشروعة عبر المصادر مع الحفاظ على الأمان.
لنفترض سيناريو يحتاج فيه تطبيق ويب مستضاف على http://example.com
إلى جلب بيانات من خادم واجهة برمجة تطبيقات مستضاف على http://api.example.net
. بدون CORS، سيحظر المتصفح هذا الطلب بسبب سياسة SOP. تسمح CORS لخادم واجهة برمجة التطبيقات بتحديد المصادر المسموح لها بالوصول إلى موارده بشكل صريح، مما يمكن تطبيق الويب من العمل بشكل صحيح.
كيف تعمل سياسة CORS: الأساسيات
تعمل CORS من خلال سلسلة من ترويسات HTTP المتبادلة بين العميل (المتصفح) والخادم. يستخدم الخادم هذه الترويسات لإبلاغ المتصفح بما إذا كان مسموحًا له بالوصول إلى المورد المطلوب. ترويسة HTTP الرئيسية المعنية هي Access-Control-Allow-Origin
.
السيناريو 1: الطلب البسيط
الطلب "البسيط" هو طلب GET، أو HEAD، أو POST يفي بمعايير محددة (على سبيل المثال، تكون قيمة ترويسة Content-Type
هي واحدة من application/x-www-form-urlencoded
، أو multipart/form-data
، أو text/plain
). في هذه الحالة، يرسل المتصفح الطلب مباشرة إلى الخادم، ويستجيب الخادم بترويسة Access-Control-Allow-Origin
.
طلب العميل (من http://example.com):
GET /data HTTP/1.1
Host: api.example.net
Origin: http://example.com
استجابة الخادم (من http://api.example.net):
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
Content-Type: application/json
{
"data": "Some data from the server"
}
في هذا المثال، يستجيب الخادم بـ Access-Control-Allow-Origin: http://example.com
، مما يشير إلى أن الطلبات من http://example.com
مسموح بها. إذا لم يتطابق المصدر في الطلب مع القيمة الموجودة في ترويسة Access-Control-Allow-Origin
(أو إذا كانت الترويسة غير موجودة)، فسيقوم المتصفح بحظر الاستجابة ومنع النص البرمجي من جانب العميل من الوصول إلى البيانات.
السيناريو 2: الطلب التمهيدي (للطلبات المعقدة)
بالنسبة للطلبات الأكثر تعقيدًا، مثل تلك التي تستخدم أساليب HTTP مثل PUT، أو DELETE، أو تلك التي تحتوي على ترويسات مخصصة، يقوم المتصفح بإجراء طلب "تمهيدي" (preflight) باستخدام أسلوب HTTP OPTIONS. يطلب هذا الطلب التمهيدي الإذن من الخادم قبل إرسال الطلب الفعلي. يستجيب الخادم بترويسات تحدد الأساليب والترويسات والمصادر المسموح بها.
طلب العميل التمهيدي (من http://example.com):
OPTIONS /data HTTP/1.1
Host: api.example.net
Origin: http://example.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header
استجابة الخادم (من http://api.example.net):
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
Access-Control-Allow-Methods: GET, PUT, DELETE
Access-Control-Allow-Headers: X-Custom-Header, Content-Type
Access-Control-Max-Age: 3600
شرح الترويسات:
Access-Control-Allow-Origin: http://example.com
- تشير إلى أن الطلبات منhttp://example.com
مسموح بها.Access-Control-Allow-Methods: GET, PUT, DELETE
- تحدد أساليب HTTP المسموح بها للطلبات عبر المصادر.Access-Control-Allow-Headers: X-Custom-Header, Content-Type
- تسرد الترويسات المخصصة المسموح بها في الطلب الفعلي.Access-Control-Max-Age: 3600
- تحدد المدة (بالثواني) التي يمكن للمتصفح تخزين استجابة الطلب التمهيدي مؤقتًا. يساعد هذا في تقليل عدد الطلبات التمهيدية.
إذا أشارت استجابة الخادم التمهيدية إلى أن الطلب مسموح به، يتابع المتصفح الطلب الفعلي. وإلا، يقوم المتصفح بحظر الطلب.
طلب العميل الفعلي (من http://example.com):
PUT /data HTTP/1.1
Host: api.example.net
Origin: http://example.com
X-Custom-Header: some-value
Content-Type: application/json
{
"data": "Some data to be updated"
}
استجابة الخادم (من http://api.example.net):
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
Content-Type: application/json
{
"status": "Data updated successfully"
}
ترويسات CORS الشائعة
فيما يلي تفصيل لترويسات CORS الرئيسية التي تحتاج إلى فهمها:
Access-Control-Allow-Origin
: هذه الترويسة هي الأكثر أساسية. تحدد المصدر (المصادر) المسموح لها بالوصول إلى المورد. تشمل القيم الممكنة:- مصدر محدد (مثل
http://example.com
). *
(حرف بدل): هذا يسمح بالطلبات من أي مصدر. استخدمه بحذر، لأنه يمكن أن يضر بالأمان إذا كانت هناك بيانات حساسة متضمنة. يجب تجنبه بشكل عام في بيئات الإنتاج.
- مصدر محدد (مثل
Access-Control-Allow-Methods
: تحدد هذه الترويسة أساليب HTTP (مثل GET, POST, PUT, DELETE) المسموح بها للطلبات عبر المصادر. يتم استخدامها في استجابة الطلب التمهيدي.Access-Control-Allow-Headers
: تسرد هذه الترويسة الترويسات المخصصة المسموح بها في الطلبات عبر المصادر. يتم استخدامها أيضًا في استجابة الطلب التمهيدي.Access-Control-Allow-Credentials
: تشير هذه الترويسة إلى ما إذا كان الخادم يسمح بتضمين بيانات الاعتماد (مثل ملفات تعريف الارتباط، ترويسات التفويض) في الطلبات عبر المصادر. يجب ضبطها علىtrue
إذا كنت بحاجة إلى إرسال بيانات الاعتماد. على جانب العميل، تحتاج أيضًا إلى ضبطwithCredentials = true
على كائن XMLHttpRequest.Access-Control-Expose-Headers
: بشكل افتراضي، لا تعرض المتصفحات سوى مجموعة محدودة من ترويسات الاستجابة (مثلCache-Control
,Content-Language
,Content-Type
,Expires
,Last-Modified
,Pragma
) للنصوص البرمجية من جانب العميل. إذا كنت ترغب في عرض ترويسات أخرى، فأنت بحاجة إلى إدراجها في ترويسةAccess-Control-Expose-Headers
.Access-Control-Max-Age
: تحدد هذه الترويسة الحد الأقصى للوقت (بالثواني) الذي يمكن للمتصفح فيه تخزين الطلب التمهيدي مؤقتًا. تقلل القيمة الأطول من عدد الطلبات التمهيدية، مما يحسن الأداء.
سياسة CORS في لغات البرمجة من جانب الخادم المختلفة
يتضمن تطبيق CORS عادةً تكوين تطبيقك من جانب الخادم لإرسال ترويسات CORS المناسبة. فيما يلي أمثلة لكيفية القيام بذلك في لغات وأطر عمل مختلفة:
Node.js مع Express
يمكنك استخدام حزمة الوسيط cors
:
const express = require('express');
const cors = require('cors');
const app = express();
// Enable CORS for all origins (USE WITH CAUTION IN PRODUCTION)
app.use(cors());
// Alternatively, configure CORS for specific origins
// app.use(cors({
// origin: 'http://example.com'
// }));
app.get('/data', (req, res) => {
res.json({ message: 'This is CORS-enabled for all origins!' });
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
Python مع Flask
يمكنك استخدام ملحق Flask-CORS
:
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
# Alternatively, configure CORS for specific origins
# CORS(app, resources={r"/api/*": {"origins": "http://example.com"}})
@app.route("/data")
def hello():
return {"message": "This is CORS-enabled for all origins!"}
if __name__ == '__main__':
app.run(debug=True)
Java مع Spring Boot
يمكنك تكوين CORS في تطبيق Spring Boot الخاص بك باستخدام التعليقات التوضيحية أو فئات التكوين:
باستخدام التعليقات التوضيحية:
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@CrossOrigin(origins = "http://example.com") // Allow requests from http://example.com
public class DataController {
@GetMapping("/data")
public String getData() {
return "This is CORS-enabled for http://example.com!";
}
}
باستخدام التكوين:
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/data")
.allowedOrigins("http://example.com") // Allow requests from http://example.com
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("*");
}
}
PHP
"This is CORS-enabled for http://example.com!");
echo json_encode($data);
?>
سياسة CORS والاعتبارات الأمنية
بينما تُمكّن CORS الطلبات عبر المصادر، فمن الضروري تطبيقها بشكل آمن. فيما يلي بعض الاعتبارات المهمة:
- تجنب استخدام
*
لـAccess-Control-Allow-Origin
في بيئة الإنتاج: هذا يسمح بالطلبات من أي مصدر، مما قد يشكل خطرًا أمنيًا. بدلاً من ذلك، حدد صراحةً المصادر المسموح لها بالوصول إلى مواردك. - التحقق من صحة ترويسة
Origin
على جانب الخادم: حتى لو كنت تستخدم إطار عمل يعالج تكوين CORS، فمن الممارسات الجيدة التحقق من صحة ترويسةOrigin
على جانب الخادم لضمان أن الطلب يأتي من مصدر متوقع. - كن حذرًا بشأن
Access-Control-Allow-Credentials
: إذا كنت تستخدم بيانات الاعتماد (مثل ملفات تعريف الارتباط، ترويسات التفويض)، فتأكد من ضبطAccess-Control-Allow-Credentials: true
على جانب الخادم وwithCredentials = true
على جانب العميل. ومع ذلك، كن على علم بأن استخدامAccess-Control-Allow-Origin: *
غير مسموح به عند ضبطAccess-Control-Allow-Credentials
علىtrue
. يجب عليك تحديد المصادر المسموح بها بشكل صريح. - تكوين
Access-Control-Allow-Methods
وAccess-Control-Allow-Headers
بشكل صحيح: اسمح فقط بأساليب HTTP والترويسات الضرورية ليعمل تطبيقك بشكل صحيح. هذا يساعد على تقليل سطح الهجوم. - استخدام HTTPS: استخدم دائمًا HTTPS لتطبيقات الويب وواجهات برمجة التطبيقات الخاصة بك لحماية البيانات أثناء النقل.
استكشاف أخطاء CORS وإصلاحها
قد يكون تصحيح أخطاء CORS محبطًا. فيما يلي بعض المشكلات الشائعة وكيفية حلها:
- "No 'Access-Control-Allow-Origin' header is present on the requested resource": هذا هو خطأ CORS الأكثر شيوعًا. ويعني أن الخادم لا يرسل ترويسة
Access-Control-Allow-Origin
في استجابته. تحقق مرة أخرى من تكوين جانب الخادم للتأكد من إرسال الترويسة بشكل صحيح. - "Response to preflight request doesn't pass access control check: It does not have HTTP ok status": يشير هذا الخطأ إلى فشل الطلب التمهيدي. يمكن أن يحدث هذا إذا لم يتم تكوين الخادم للتعامل مع طلبات OPTIONS أو إذا لم يتم تكوين ترويسات
Access-Control-Allow-Methods
أوAccess-Control-Allow-Headers
بشكل صحيح. - "The value of the 'Access-Control-Allow-Origin' header in the response is not equal to the origin in the request": يعني هذا الخطأ أن المصدر في الطلب لا يتطابق مع القيمة الموجودة في ترويسة
Access-Control-Allow-Origin
. تأكد من أن الخادم يرسل المصدر الصحيح في الاستجابة. - التخزين المؤقت للمتصفح: في بعض الأحيان، يمكن للمتصفحات تخزين استجابات CORS مؤقتًا، مما قد يؤدي إلى سلوك غير متوقع. حاول مسح ذاكرة التخزين المؤقت للمتصفح أو استخدام متصفح مختلف لمعرفة ما إذا كان ذلك يحل المشكلة. يمكنك أيضًا استخدام ترويسة
Access-Control-Max-Age
للتحكم في مدة تخزين المتصفح لاستجابة الطلب التمهيدي مؤقتًا.
أدوات تصحيح الأخطاء:
- أدوات مطوري المتصفح: استخدم أدوات مطوري المتصفح (يتم الوصول إليها عادةً بالضغط على F12) لفحص طلبات الشبكة واستجاباتها. ابحث عن الترويسات المتعلقة بـ CORS ورسائل الخطأ.
- أدوات فحص CORS عبر الإنترنت: هناك أدوات عبر الإنترنت يمكن أن تساعدك في اختبار تكوين CORS الخاص بك. ترسل هذه الأدوات طلبًا إلى الخادم الخاص بك وتحلل ترويسات الاستجابة لتحديد المشكلات المحتملة.
سيناريوهات CORS المتقدمة
بينما تعتبر مفاهيم CORS الأساسية مباشرة نسبيًا، هناك بعض السيناريوهات الأكثر تقدمًا التي يجب مراعاتها:
- CORS مع النطاقات الفرعية: إذا كنت بحاجة إلى السماح بالطلبات من نطاقات فرعية متعددة (مثل
app1.example.com
,app2.example.com
)، فلا يمكنك ببساطة استخدام حرف بدل مثل*.example.com
في ترويسةAccess-Control-Allow-Origin
. بدلاً من ذلك، ستحتاج إلى إنشاء ترويسةAccess-Control-Allow-Origin
ديناميكيًا بناءً على ترويسةOrigin
في الطلب. تذكر التحقق من صحة المصدر مقابل قائمة بيضاء من النطاقات الفرعية المسموح بها لمنع الثغرات الأمنية. - CORS مع مصادر متعددة: إذا كنت بحاجة إلى السماح بالطلبات من مصادر محددة متعددة، فلا يمكنك تحديد مصادر متعددة في ترويسة
Access-Control-Allow-Origin
(على سبيل المثال،Access-Control-Allow-Origin: http://example.com, http://another.com
غير صالح). بدلاً من ذلك، ستحتاج إلى إنشاء ترويسةAccess-Control-Allow-Origin
ديناميكيًا بناءً على ترويسةOrigin
في الطلب. - CORS وشبكات توصيل المحتوى (CDNs): عند استخدام شبكة توصيل محتوى لخدمة واجهة برمجة التطبيقات الخاصة بك، تحتاج إلى تكوين شبكة توصيل المحتوى لإعادة توجيه ترويسة
Origin
إلى خادم المصدر الخاص بك وتخزين ترويسةAccess-Control-Allow-Origin
مؤقتًا بشكل صحيح. راجع وثائق مزود شبكة توصيل المحتوى للحصول على إرشادات محددة.
أفضل ممارسات CORS
لضمان تنفيذ CORS آمن وفعال، اتبع أفضل الممارسات التالية:
- مبدأ الامتياز الأقل: اسمح فقط بالحد الأدنى من المصادر والأساليب والترويسات الضرورية ليعمل تطبيقك بشكل صحيح.
- مراجعة تكوين CORS بانتظام: مع تطور تطبيقك، راجع تكوين CORS بانتظام للتأكد من أنه لا يزال مناسبًا وآمنًا.
- استخدام إطار عمل أو مكتبة: استفد من أطر العمل أو المكتبات الحالية التي توفر دعمًا مدمجًا لـ CORS. يمكن أن يبسط هذا التنفيذ ويقلل من خطر الأخطاء.
- مراقبة انتهاكات CORS: قم بتنفيذ المراقبة لاكتشاف انتهاكات CORS المحتملة والاستجابة لها.
- ابق على اطلاع: ابق على اطلاع بأحدث مواصفات CORS والتوصيات الأمنية.
الخاتمة
تعد CORS آلية أمان حاسمة تُمكّن الطلبات الخاضعة للرقابة عبر المصادر في تطبيقات الويب. إن فهم كيفية عمل CORS وكيفية تكوينها بشكل صحيح أمر ضروري لكل مطور ويب. باتباع الإرشادات وأفضل الممارسات الموضحة في هذا الدليل الشامل، يمكنك بناء تطبيقات ويب آمنة وفعالة تتفاعل بسلاسة مع الموارد من مصادر مختلفة.
تذكر دائمًا إعطاء الأولوية للأمان وتجنب استخدام تكوينات CORS المتساهلة بشكل مفرط. من خلال النظر بعناية في الآثار الأمنية لإعدادات CORS الخاصة بك، يمكنك حماية تطبيقاتك وبياناتك من الوصول غير المصرح به.
نأمل أن يكون هذا الدليل قد ساعدك في إزالة الغموض عن CORS. نتمنى لك برمجة ممتعة!