اختار الكاتب فتيات البرمجة لتلقي تبرع كجزء من برنامج اكتب للتبرعات.
المقدمة
عند زيارتك لموقع ويب، يتم استخدام موارد مختلفة لتحميله وعرضه. على سبيل المثال، عندما تذهب إلى https://www.digitalocean.com
، يقوم متصفحك بتنزيل الـ HTML و CSS مباشرةً من digitalocean.com
. ومع ذلك، يتم تنزيل الصور والأصول الأخرى من assets.digitalocean.com
، وتحميل النصوص التحليلية من نطاقاتها المحددة.
تستخدم بعض المواقع مجموعة متعددة من الخدمات والأنماط والنصوص لتحميل وعرض محتواها، وسيقوم متصفحك بتنفيذ كل ذلك. لا يعرف المتصفح ما إذا كان الكود ضارًا، لذا فإن مسؤولية المطور هي حماية المستخدمين. نظرًا لأنه يمكن أن تكون هناك العديد من الموارد على موقع ويب، فإن وجود ميزة في المتصفح تسمح فقط بالموارد المعتمدة هو وسيلة جيدة لضمان عدم تعرض المستخدمين للمخاطر. هذا هو الغرض من سياسات أمان المحتوى (CSPs).
باستخدام رأس CSP، يمكن للمطور السماح صراحة بتشغيل بعض الموارد مع منع جميع الآخرين. نظرًا لأن معظم المواقع يمكن أن تحتوي على ما يصل إلى 100 مورد، ويجب أن يتم الموافقة على كل واحد لفئة معينة من المورد، يمكن أن يكون تنفيذ CSP مهمة مملة. ومع ذلك، ستكون مواقع الويب التي تحتوي على CSP أكثر أمانًا لأنها تضمن أن يتم السماح فقط بالموارد المعتمدة بالتشغيل.
في هذا البرنامج التعليمي، ستقوم بتنفيذ CSP في تطبيق Django أساسي. ستقوم بتخصيص CSP للسماح ببعض النطاقات والموارد الداخلية للتشغيل. يمكنك، اختياريًا، أيضًا استخدام Sentry لتسجيل الانتهاكات.
المتطلبات المسبقة
لإكمال هذا البرنامج التعليمي، ستحتاج إلى:
- A working Django project (version 3 or greater is preferred), either on your local machine or a DigitalOcean Droplet. If you don’t have one, you can create one with the tutorial, How to Install Django and Set Up a Development Environment on Ubuntu 20.04.
- A web browser like Firefox or Chrome and an understanding of browser network tools. For more on using browser network tools, check out the product documentation for the Network Monitor in Firefox or the DevTools Network Tab in Chrome. For more general guidance on browser developer tools, see the guide: What are Browser Developer Tools?
- معرفة بلغة Python 3 و Django، التي يمكنك الحصول عليها من سلسلة البرامج التعليمية، كيفية البرمجة بلغة Python و تطوير Django.
- حساب على Sentry لتتبع انتهاكات CSP (اختياري).
الخطوة 1 — إنشاء عرض توضيحي
في هذه الخطوة، ستقوم بتعديل كيفية تعامل تطبيقك مع العروض لكي تتمكن من إضافة دعم CSP.
كمتطلب أساسي، قمت بتثبيت Django وإعداد مشروع عينة. العرض الافتراضي في Django بسيط جدًا لعرض كل إمكانيات وسيط CSP، لذا ستقوم بإنشاء صفحة HTML بسيطة لهذا البرنامج التعليمي.
انتقل إلى مجلد المشروع الذي قمت بإنشائه في المتطلبات المسبقة:
أثناء تواجدك داخل مجلد django-apps
، قم بإنشاء بيئة افتراضية. سنطلق عليها اسم env
، ولكن يجب عليك استخدام اسم ذو معنى بالنسبة لك ولمشروعك.
الآن، قم بتفعيل البيئة الافتراضية باستخدام الأمر التالي:
داخل البيئة الافتراضية، قم بإنشاء ملف views.py
في مجلد مشروعك باستخدام nano
، أو محرر النصوص المفضل لديك:
الآن، ستضيف عرضًا أساسيًا سيقوم بعرض قالب index.html
الذي ستقوم بإنشائه لاحقًا. أضف ما يلي إلى views.py
:
قم بحفظ الملف وإغلاقه عند الانتهاء.
قم بإنشاء قالب index.html
في مجلد templates
جديد:
أضف ما يلي إلى index.html
:
العرض الذي قمت بإنشائه سيقوم بعرض هذه الصفحة HTML البسيطة. سيعرض النص Hello, Sammy! بالإضافة إلى صورة لـ Sammy the Shark.
قم بحفظ الملف وإغلاقه عند الانتهاء.
للوصول إلى هذا العرض، ستحتاج إلى تحديث urls.py
:
قم بإستيراد ملف views.py
وأضف مسارًا جديدًا عن طريق إضافة الأسطر المظللة:
سيكون العرض الجديد الذي قمت بإنشائه مرئيًا الآن عندما تزور /
(عند تشغيل التطبيق).
قم بحفظ الملف وإغلاقه.
أخيرًا، ستحتاج إلى تحديث INSTALLED_APPS
لتضمين testsite
في settings.py
:
هنا، يتم إضافة testsite
إلى قائمة التطبيقات في settings.py
بحيث يمكن لـ Django أن يفترض بعض الأمور حول هيكل مشروعك. في هذه الحالة، سيفترض أن المجلد templates
يحتوي على قوالب Django التي يمكنك استخدامها لتقديم العروض.
من دليل مشروعك الرئيسي (testsite
)، ابدأ خادم تطوير Django بالأمر التالي، مع استبدال your-server-ip
بعنوان IP الخاص بخادمك.
افتح متصفحًا وقم بزيارة your-server-ip:8000
. يجب أن تبدو الصفحة مشابهة لهذا:
في هذه المرحلة، تعرض الصفحة صورة الملف الشخصي لـ Sammy the Shark. تحت الصورة، يوجد نص Hello, Sammy! بخط أزرق.
لإيقاف خادم تطوير Django، اضغط على CONTROL-C
.
في هذه الخطوة، قمت بإنشاء عرض أساسي يعمل كصفحة رئيسية لمشروع Django الخاص بك. في الخطوة التالية، ستضيف دعم CSP إلى تطبيقك.
الخطوة 2 — تثبيت وسيط CSP
في هذه الخطوة، ستقوم بتثبيت وتنفيذ وسيط CSP بحيث يمكنك إضافة رؤوس CSP والعمل مع ميزات CSP في عروضك. يضيف الوسيط وظائف إضافية إلى أي طلب أو استجابة يتعامل Django معها. في هذه الحالة، يضيف وسيط Django-CSP دعم CSP إلى استجابات Django.
أولاً، ستقوم بتثبيت وسيط CSP Middleware من Mozilla في مشروع Django الخاص بك باستخدام pip
، مدير الحزم الخاص بـ Python. استخدم الأمر التالي لتثبيت الحزمة اللازمة من PyPi، فهو فهرس الحزم الخاص بـ Python. لتشغيل الأمر، يمكنك إما إيقاف خادم تطوير Django باستخدام CONTROL-C
أو فتح علامة تبويب جديدة في وحدة التحكم الخاصة بك:
بعد ذلك، قم بإضافة الوسيط إلى إعدادات مشروع Django الخاصة بك. افتح settings.py
:
بعد تثبيت django-csp
، يمكنك الآن إضافة الوسيط في settings.py
. سيقوم هذا بإضافة رؤوس CSP إلى استجاباتك.
أضف السطر التالي إلى مصفوفة تكوين MIDDLEWARE
:
احفظ وأغلق الملف عند الانتهاء. مشروع Django الخاص بك الآن يدعم CSPs. في الخطوة التالية، ستبدأ في إضافة رؤوس CSP.
الخطوة 3 — تنفيذ رأس CSP
الآن بعد أن يدعم مشروعك CSPs، فهو جاهز لتعزيز الأمان. لتحقيق ذلك، ستقوم بتكوين المشروع لإضافة رؤوس CSP إلى استجاباتك. رأس CSP هو ما يخبر المتصفح كيفية التصرف عندما يواجه نوعًا معينًا من المحتوى. لذا، إذا قال الرأس السماح فقط بالصور من نطاق معين، فإن المتصفح سيسمح فقط بالصور من ذلك النطاق.
باستخدام نانو أو محرر النصوص المفضل لديك، افتح settings.py
:
حدد المتغيرات التالية في أي مكان في الملف:
هذه القواعد هي النموذج الأساسي لـ CSP الخاص بك. تشير هذه الأسطر إلى المصادر المسموح بها للصور والأنماط والنصوص على التوالي. في الوقت الحالي، تحتوي جميعها على سلسلة 'self'
، والتي تعني أنه يُسمح فقط بالموارد من نطاقك الخاص.
احفظ وأغلق الملف عند الانتهاء.
شغّل مشروع Django الخاص بك باستخدام الأمر التالي:
عند زيارة عنوان-الخادم-الخاص-بك:8000
، سترى أن الموقع معطّل:
كما هو متوقع، لا تظهر الصورة ويظهر النص بالتنسيق الافتراضي (عريض أسود). هذا يعني أن رأس CSP يتم فرضه، وأن صفحتنا الآن أكثر أمانًا. نظرًا لأن العرض الذي قمت بإنشائه مسبقًا يشير إلى أنماط وصور من نطاقات ليست من نطاقك الخاص، يمنع المتصفحها.
لديك الآن مشروع يحتوي على CSP يعمل يُخبر المتصفح بحظر الموارد التي ليست من نطاقك. فيما بعد، ستقوم بتعديل CSP للسماح بموارد محددة، مما سيُصلح صورة الموقع الرئيسية المفقودة والتنسيق.
الخطوة 4 — تعديل CSP للسماح بالموارد الخارجية
الآن بعد أن لديك CSP الأساسي، ستقوم بتعديله استنادًا إلى ما تستخدمه على موقعك. كمثال، الموقع الذي يستخدم خطوط Adobe ومقاطع فيديو YouTube المضمنة سيحتاج إلى السماح بتلك الموارد. ومع ذلك، إذا كان موقعك يعرض الصور فقط من داخل نطاقك الخاص، فيمكنك ترك إعدادات الصور على القيم الافتراضية القياسية الصارمة.
الخطوة الأولى هي العثور على كل مورد تحتاج إلى الموافقة عليه. يمكنك استخدام أدوات تطوير المتصفح الخاص بك للقيام بذلك. افتح مراقب الشبكة في عنصر التفتيش، قم بتحديث الصفحة، وانظر إلى الموارد المحظورة:
سجل الشبكة يظهر أن موردين من الموارد يتم حظرهم بواسطة CSP: ورقة أنماط من fonts.googleapis.com
وصورة من html.sammy-codes.com
. للسماح بتلك الموارد في رأس CSP، ستحتاج إلى تعديل المتغيرات في settings.py
.
للسماح بالموارد من النطاقات الخارجية، أضف النطاق إلى جزء من CSP الذي يتطابق مع نوع الملف. لذا، للسماح بصورة من html.sammy-codes.com
، ستضيف html.sammy-codes.com
إلى CSP_STYLE_SRC
.
افتح settings.py
وأضف ما يلي إلى متغير CSP_STYLE_SRC
:
الآن، بدلاً من السماح فقط بالصور من نطاقك، يسمح الموقع أيضًا بالصور من html.sammy-codes.com
.
تستخدم صفحة الفهرسة خطوط Google. تزوّد Google موقعك بالخطوط (من https://fonts.gstatic.com
) وبورقة أنماط لتطبيقها (من https://fonts.googleapis.com
). للسماح بتحميل الخطوط، أضف ما يلي إلى CSP الخاص بك:
على غرار السماح بالصور من html.sammy-codes.com
، ستسمح أيضًا بورقات الأنماط من fonts.googleapis.com
والخطوط من fonts.gstatic.com
. للسياق، يُستخدم ورق الأنماط المحمّل من fonts.googleapis.com
لتطبيق الخطوط. تُحمّل الخطوط بذاتها من fonts.gstatic.com
.
احفظ وأغلق الملف.
تحذير: بالمثل لـself
، هناك كلمات أخرى مثل unsafe-inline
، unsafe-eval
، أو unsafe-hashes
التي يمكن استخدامها في CSP. من الأفضل بشدة تجنب استخدام هذه القواعد في CSP الخاص بك. على الرغم من أن هذه القواعد ستُسهّل التنفيذ، إلا أنها يمكن أن تُستخدم لتفادي CSP وجعلها غير فعّالة.
لمزيد من المعلومات، انظر إلى وثائق منتج Mozilla لـ “Unsafe inline script”.
الآن، ستُسمح لـ Google Fonts بتحميل الأنماط والخطوط على موقعك، وستُسمح لـhtml.sammy-codes.com
بتحميل الصور. ومع ذلك، عندما تزور صفحة على خادمك، قد تلاحظ أن الصور فقط تُحمّل الآن. هذا لأن الأنماط المضمنة في HTML والتي تُستخدم لتطبيق الخطوط ليست مُسموح بها. ستُصلح ذلك في الخطوة التالية.
الخطوة 5 — العمل مع النصوص والأنماط الداخلية
في هذه النقطة، قمت بتعديل CSP للسماح بالموارد الخارجية. ولكن الموارد الداخلية، مثل الأنماط والنصوص في عرضك، لا تزال غير مسموح بها. في هذه الخطوة، ستجعل هذه العناصر تعمل بحيث يمكنك تطبيق تنسيق الخط.
هناك طريقتان للسماح بالنصوص والأنماط الداخلية: الأرقام العشوائية والهاش. إذا وجدت أنك تقوم بتعديل النصوص والأنماط الداخلية بشكل متكرر، استخدم الأرقام العشوائية لتجنب التغييرات المتكررة على CSP الخاص بك. إذا كنت نادرًا ما تقوم بتحديث النصوص والأنماط الداخلية، فاستخدام الهاش هو نهج معقول.
استخدام nonce
للسماح بالنصوص الداخلية
أولاً، ستستخدم النهج nonce. النهج nonce هو رمز مولد عشوائي يكون فريدًا لكل طلب. إذا زار شخصان موقعك، سيحصل كل منهما على nonce
فريد يتم تضمينه في النصوص والأنماط الداخلية التي توافق عليها. فكر في النهج nonce ككلمة مرور مرة واحدة توافق أجزاء معينة من الموقع لتشغيل جلسة واحدة فقط.
لإضافة دعم nonce إلى مشروعك، ستقوم بتحديث CSP في settings.py
. افتح الملف للتعديل:
أضف script-src
في CSP_INCLUDE_NONCE_IN
في ملف settings.py
.
قم بتعريف CSP_INCLUDE_NONCE_IN
في أي مكان في الملف وأضف 'script-src'
إليه:
CSP_INCLUDE_NONCE_IN
يشير إلى النصوص الخطية التي يُسمح لك بإضافة سمة nonce
إليها. يُعالج CSP_INCLUDE_NONCE_IN
على أنه مصفوفة لأن مصادر البيانات المتعددة تدعم الأرقام المرجعية (على سبيل المثال، style-src
).
احفظ وأغلق الملف.
يُسمح الآن بتوليد الأرقام المرجعية للنصوص الخطية عند إضافة السمة nonce
إليها في قالب العرض الخاص بك. لتجربة هذا، ستستخدم مقتطف جافا سكريبت بسيط.
افتح index.html
للتحرير:
أضف المقتطف التالي في الجزء <head>
من HTML:
هذا المقتطف يقوم بطباعة Hello from the console!"
في وحدة التحكم بالمتصفح. ومع ذلك، نظرًا لأن مشروعك يحتوي على سياسة أمان للمحتوى تسمح فقط بالنصوص الخطية إذا كانت تحتوي على nonce
، فلن يتم تشغيل هذا النص وبدلاً من ذلك سيتم إنتاج خطأ.
يمكنك رؤية هذا الخطأ في وحدة التحكم بالمتصفح عندما تقوم بتحديث الصفحة:
يتم تحميل الصورة لأنك سمحت بالموارد الخارجية في الخطوة السابقة. كما هو متوقع، التنسيق حاليًا هو الافتراضي لأنك لم تسمح بعد بالأنماط الخطية. كما هو متوقع أيضًا، لم تتم طباعة رسالة وحدة التحكم بالمتصفح ولكن عادت بخطأ. ستحتاج إلى إعطائها nonce
للموافقة عليها.
يمكنك فعل ذلك عن طريق إضافة nonce="{{request.csp_nonce}}"
إلى هذا السكريبت كخاصية. افتح index.html
للتحرير وأضف الجزء المظلل كما هو موضح هنا:
احفظ وأغلق الملف عند الانتهاء.
إذا قمت بتحديث الصفحة، سيتم تنفيذ السكريبت الآن:
عندما تنظر في عنصر التفتيش، ستلاحظ عدم وجود قيمة للخاصية:
القيمة لا تظهر لأسباب أمنية. لقد قام المتصفح بمعالجة القيمة بالفعل. إنها مخفية بحيث لا يمكن لأي سكريبت لديه الوصول إلى DOM الوصول إليها وتطبيقها على سكريبت آخر. إذا قمت بـ عرض مصدر الصفحة بدلاً من ذلك، هذا ما تلقاه المتصفح:
لاحظ أنه في كل مرة تقوم فيها بتحديث الصفحة، تتغير قيمة nonce
. يحدث هذا لأن برنامج الوسيط CSP في مشروعنا يولد nonce
جديدة لكل طلب.
تتم إضافة قيم nonce
هذه إلى رأس CSP عندما يتلقى المتصفح الاستجابة:
كل طلب يقوم به المتصفح إلى موقعك سيكون له قيمة nonce
فريدة لهذا السكريبت. نظرًا لأن الـ nonce
مقدم في رأس CSP، فهذا يعني أن خادم Django وافق على تشغيل تلك النصوص المحددة.
لقد قمت بتحديث مشروعك للعمل مع nonce، والذي يمكن تطبيقه على موارد متعددة. على سبيل المثال، يمكنك تطبيقه على الأنماط أيضًا، من خلال تحديث CSP_INCLUDE_NONCE_IN
للسماح style-src
. ولكن هناك نهج أبسط للموافقة على الموارد الداخلية، وهذا ما ستفعله فيما بعد.
استخدام التجزئة للسماح بالأنماط الداخلية
طريقة أخرى للسماح بالنصوص والأنماط الداخلية هي باستخدام التجزئة. التجزئة هي معرف فريد للمورد الداخلي المعطى.
كمثال، هذا هو النمط الداخلي في قالبنا:
حاليًا، إلا أن الأنماط لا تعمل. عند عرض الموقع في المتصفح، تحميل الصور بنجاح، ولكن الخطوط والأنماط لا يتم تطبيقها:
في وحدة التحكم للمتصفح، ستجد خطأ بأن النمط الداخلي ينتهك سياسة الأمان. (قد تظهر أخطاء أخرى، ولكن ابحث عن الخطأ المتعلق بالنمط الداخلي.)
يتم إنتاج الخطأ لأن النمط لم يتم الموافقة عليه من قبل سياسة الأمان لدينا. ولكن، لاحظ أن الخطأ يوفر التجزئة اللازمة للموافقة على مقتطف النمط. هذه التجزئة فريدة من نوعها لهذا المقتطف النمطي الخاص. لن يكون لدى مقتطفات أخرى نفس التجزئة أبدًا. عند وضع هذه التجزئة داخل سياسة الأمان، في أي وقت يتم تحميل هذا النمط المحدد، سيتم الموافقة عليه. ولكن، إذا قمت بتعديل هذه الأنماط في أي وقت، ستحتاج إلى الحصول على التجزئة الجديدة واستبدال القديمة بها في سياسة الأمان.
الآن، ستقوم بتطبيق التجزئة عن طريق إضافتها إلى CSP_STYLE_SRC
في settings.py
، على النحو التالي:
إضافة التجزئة sha256-...
إلى قائمة CSP_STYLE_SRC
ستسمح للمتصفح بتحميل ورقة الأنماط دون أي أخطاء.
احفظ وأغلق الملف.
الآن، أعد تحميل الموقع في المتصفح، ويجب أن تحمّل الخطوط والأنماط بنجاح:
تعمل الأنماط والنصوص المضمّنة الآن بشكل صحيح. في هذه الخطوة، استخدمت نهجين مختلفين، الأول بواسطة الرموز السرية والثاني بواسطة العناوين الهاش، للسماح بالأنماط والنصوص المضمّنة.
ولكن، هناك مشكلة مهمة يجب معالجتها. إن سياسات أمان مصادر المحتوى هي مهمة للغاية للحفاظ على الأمان، لكنها تستلزم صيانة مستمرة، خاصة للمواقع الكبيرة. قد تحتاج إلى طريقة لتتبع حينما تمنع سياسة أمان مصادر المحتوى موردًا حتى تتمكن من تحديد ما إذا كان موردًا خبيثًا أم مجرد جزء معطل من موقعك. في الخطوة القادمة، ستستخدم Sentry لتسجيل وتتبع جميع الانتهاكات التي تنتجها سياسة أمان مصادر المحتوى الخاصة بك.
الخطوة 6 — الإبلاغ عن الانتهاكات باستخدام Sentry (اختياري)
نظرًا لصرامة سياسات أمان مصادر المحتوى، فإنه من الجيد معرفة عندما تمنع محتوى معين — خاصةً نظرًا لأن منع المحتوى يعني على الأرجح عدم عمل بعض الوظائف على موقعك. يمكن لأدوات مثل Sentry إعلامك عندما تمنع سياسة أمان مصادر المحتوى طلبات المستخدمين. في هذه الخطوة، ستقوم بتكوين Sentry لتسجيل والإبلاغ عن انتهاكات سياسة أمان مصادر المحتوى.
كمتطلب أساسي، قمت بالتسجيل في حساب مع Sentry. الآن ستقوم بإنشاء مشروع.
في الزاوية العلوية اليسرى من لوحة تحكم Sentry، انقر على علامة التبويب المشاريع:
في الزاوية العلوية اليمنى، انقر على زر إنشاء مشروع:
سترى عدداً من الشعارات مع عنوان يشير إلى اختر منصة. اختر Django:
ثم، في الأسفل، اسم مشروعك (لهذا المثال، سنستخدم sammys-tutorial
)، وانقر فوق زر إنشاء مشروع:
سيقدم لك Sentry كود مقتطف لإضافته إلى ملف settings.py
. قم بحفظ هذا المقتطف لإضافته في خطوة لاحقة.
في الطرفية الخاصة بك، قم بتثبيت مجموعة أدوات Sentry:
افتح settings.py
مثل هذا:
أضف ما يلي إلى نهاية الملف، وتأكد من استبدال SENTRY_DSN
بالقيمة من لوحة المعلومات:
يُقدم هذا الكود من Sentry بحيث يمكنه تسجيل أي أخطاء تحدث في تطبيقك. إنه التكوين الافتراضي لـ Sentry ويهيئ Sentry لتسجيل المشكلات على خادمنا. من الناحية التقنية، ليس عليك تهيئة Sentry على خادمك لمخالفات CSP، ولكن في الحالة النادرة التي تحدث فيها بعض مشاكل تقديم nonces أو hashes، سيتم تسجيل هذه الأخطاء في Sentry.
قم بحفظ الملف وإغلاقه.
ثم، ارجع إلى لوحة التحكم لمشروعك وانقر فوق أيقونة العتاد للدخول إلى الإعدادات:
انتقل إلى علامة التبويب رؤوس الأمان:
انسخ report-uri
:
أضفه إلى CSP الخاص بك على النحو التالي:
تأكد من استبدال your-report-uri
بالقيمة التي قمت بنسخها من لوحة التحكم.
احفظ وأغلق ملفك. الآن، عندما يتسبب فرض CSP في انتهاك، سيقوم Sentry بتسجيله على هذا الرابط URI. يمكنك تجربة ذلك عن طريق إزالة نطاق أو تجزئة من CSP الخاص بك، أو عن طريق إزالة nonce
من النص الذي أضفته سابقًا. قم بتحميل الصفحة في المتصفح وسترى الخطأ في صفحة مشاكل Sentry:
إذا وجدت نفسك مضغوطًا بعدد السجلات، يمكنك أيضًا تعريف
CSP_REPORT_PERCENTAGE
في settings.py
لإرسال نسبة مئوية من السجلات إلى Sentry فقط.
الآن، عندما يحدث انتهاك لـ CSP، ستتلقى إشعارًا ويمكنك عرض الخطأ في Sentry.
الاستنتاج
في هذا المقال، قمت بتأمين تطبيق Django الخاص بك باستخدام سياسة أمان المحتوى. قمت بتحديث السياسة الخاصة بك للسماح بالموارد الخارجية، واستخدمت الأرقام العشوائية والهاشات للسماح بالنصوص والأنماط الداخلية. كما قمت بتكوينه لإرسال الانتهاكات إلى Sentry. كخطوة مقبلة، تحقق من وثائق Django CSP لمعرفة المزيد حول كيفية فرض سياسة أمان المحتوى الخاصة بك.