إضافة عناوين إضافية لطلب HTTP

تحتوي طلبات HTTP على عناوين مثل User-Agent أو Content-Type. بالإضافة إلى العناوين التي تضيفها المتصفحات، يمكن لتطبيقات Android إضافة عناوين إضافية، مثل Cookie أو Referrer، من خلال الإضافة EXTRA_HEADERS في Intent. لأسباب أمنية، يفلتر Chrome بعض العناوين الإضافية استنادًا إلى طريقة ومكان تشغيل الغرض.

تتطلّب طلبات متعدّدة المصادر طبقة أمان إضافية لأنّ العميل والخادم ليسا مملوكَين للجهة نفسها. يناقش هذا الدليل إطلاق هذه الطلبات من خلال علامات التبويب المخصّصة في Chrome، أي النوايا التي يتم إطلاقها من التطبيقات التي تفتح عنوان URL في علامة تبويب المتصفّح. قبل الإصدار 83 من Chrome، كان بإمكان المطوّرين إضافة أي عناوين عند تشغيل علامة تبويب مخصّصة. بدءًا من الإصدار 83، بدأ Chrome بفلترة جميع العناوين الموافق عليها باستثناء العناوين متعدّدة المصادر، لأنّ العناوين غير الموافق عليها تشكّل خطرًا أمنيًا. اعتبارًا من الإصدار 86 من Chrome، يمكن إرفاق عناوين غير مدرَجة في قائمة الموافقة بطلبات متعدّدة المصادر، وذلك عندما يكون الخادم والعميل مرتبطَين باستخدام رابط أصول رقمية. يتم تلخيص هذا السلوك في الجدول التالي:

إصدار Chrome عناوين CORS المسموح بها
قبل الإصدار 83 من Chrome مسموح به، غير مسموح به
الإصدارات من 83 إلى 85 من Chrome مدرَج في القائمة المسموح بها
من الإصدار 86 من Chrome والإصدارات الأحدث approvelisted أو non-approvelisted عند إعداد رابط لأصل رقمي

الجدول 1: فلترة عناوين CORS غير المدرَجة في قائمة الموافقة

توضّح هذه المقالة كيفية إعداد اتصال تم التحقّق منه بين الخادم والعميل واستخدامه لإرسال عناوين http المدرَجة في قائمة الموافقة وغير المدرَجة فيها. يمكنك الانتقال إلى إضافة عناوين إضافية إلى أغراض علامات التبويب المخصّصة للاطّلاع على الرمز.

خلفية

عناوين طلبات CORS المدرَجة في قائمة الموافقة مقابل عناوين طلبات CORS غير المدرَجة في قائمة الموافقة

تسمح مشاركة الموارد المتعدّدة المصادر (CORS) لتطبيق ويب من مصدر معيّن بطلب موارد من مصدر مختلف. يتم الاحتفاظ بقائمة العناوين المدرَجة في قائمة الموافقة في CORS في معيار HTML. يتم عرض أمثلة على العناوين المدرَجة في القائمة المسموح بها في الجدول التالي:

Header الوصف
accept-language تُعلن عن اللغات الطبيعية التي يفهمها العميل
content-language تصف اللغة المخصّصة للجمهور الحالي
content-type تشير إلى نوع الوسائط للمورد

الجدول 2: مثال على عناوين CORS المدرَجة في قائمة الموافقة

تُعدّ العناوين المُدرَجة في القائمة البيضاء آمنة لأنّها لا تحتوي على معلومات حساسة عن المستخدمين، ومن غير المحتمل أن تتسبّب في أن ينفّذ الخادم عمليات قد تكون ضارة.

يتم عرض أمثلة على العناوين غير المدرَجة في القائمة البيضاء في الجدول التالي:

Header الوصف
bearer-token مصادقة العميل على الخادم
الأصل تشير إلى مصدر الطلب
كعكة محلاة يحتوي على ملفات تعريف ارتباط تم ضبطها بواسطة الخادم

الجدول 3: مثال على عناوين CORS غير المدرَجة في قائمة الموافقة

لا يُنصح بإرفاق عناوين غير مدرَجة في قائمة الموافقة بطلبات CORS وفقًا لمعيار HTML، وتفترض الخوادم أنّ الطلبات متعدّدة المصادر تحتوي على عناوين مدرَجة في قائمة الموافقة فقط. سيؤدي إرسال عناوين غير مدرَجة في القائمة المسموح بها من نطاقات متعددة المصادر إلى السماح للتطبيقات الضارة التابعة لجهات خارجية بإنشاء عناوين تسيء استخدام ملفات تعريف الارتباط الخاصة بالمستخدمين التي يخزّنها Chrome (أو متصفّح آخر) ويرفقها بالطلبات. يمكن أن تصادق ملفات تعريف الارتباط على معاملات الخادم الضارة التي لا يمكن إجراؤها بطريقة أخرى.

إرفاق عناوين CORS المدرَجة في قائمة الموافقة بطلبات علامات التبويب المخصّصة

علامات التبويب المخصّصة هي طريقة خاصة لفتح صفحات الويب في علامة تبويب متصفّح مخصّصة. يمكن إنشاء نوايا علامات التبويب المخصّصة باستخدام CustomTabsIntent.Builder(). يمكنك أيضًا إرفاق عناوين بهذه النوايا باستخدام Bundle مع العلامة Browser.EXTRA_HEADERS:

CustomTabsIntent intent = new CustomTabsIntent.Builder(session).build();

Bundle headers = new Bundle();
headers.putString("bearer-token", "Some token");
headers.putString("redirect-url", "Some redirect url");   
intent.intent.putExtra(Browser.EXTRA_HEADERS, headers);

intent.launchUrl(Activity.this, Uri.parse("http://www.google.com"));

يمكننا دائمًا إرفاق العناوين المدرَجة في قائمة الموافقة بطلبات CORS في علامات التبويب المخصّصة. ومع ذلك، يفلتر Chrome العناوين التي لا تندرج ضمن القائمة المسموح بها تلقائيًا. على الرغم من أنّ المتصفّحات الأخرى قد تتصرف بشكل مختلف، على المطوّرين توقُّع حظر العناوين التي لم تتم إضافتها إلى القائمة المسموح بها بشكل عام.

الطريقة المتاحة لتضمين عناوين غير مدرَجة في القائمة المعتمدة ضمن علامات التبويب المخصّصة هي التحقّق أولاً من صحة الاتصال متعدّد المصادر باستخدام رابط وصول رقمي. يوضّح القسم التالي كيفية إعداد هذه العناوين وإطلاق هدف علامات التبويب المخصّصة باستخدام العناوين المطلوبة.

إضافة عناوين إضافية إلى أغراض علامات التبويب المخصّصة

للسماح بتمرير العناوين غير المدرَجة في قائمة الموافقة من خلال نوايا علامات التبويب المخصّصة، من الضروري إعداد رابط أصول رقمية بين تطبيق Android وتطبيق الويب، ما يثبت أنّ المؤلف يملك كلا التطبيقين.

اتّبِع الدليل الرسمي لإعداد رابط أصول رقمية. بالنسبة إلى علاقة الرابط، استخدِم "delegate_permission/common.use_as_origin"` الذي يشير إلى أنّ كلا التطبيقين ينتميان إلى المصدر نفسه بعد إثبات صحة الرابط.

إنشاء Custom Tab Intent باستخدام عناوين إضافية

تتوفّر عدة طرق لإنشاء غرض علامات التبويب المخصّصة. يمكنك استخدام أداة الإنشاء المتاحة في androidX من خلال إضافة المكتبة إلى العناصر التابعة للإنشاء:

implementation 'androidx.browser:browser:1.2.0'

أنشئ الغرض وأضِف عناوين إضافية:

CustomTabsIntent constructExtraHeadersIntent(CustomTabsSession session) {
    CustomTabsIntent intent = new CustomTabsIntent.Builder(session).build();

    // Example non-cors-approvelisted headers.
    Bundle headers = new Bundle();
    headers.putString("bearer-token", "Some token");
    headers.putString("redirect-url", "Some redirect url");
    intent.intent.putExtra(Browser.EXTRA_HEADERS, headers);
    return intent;
}

يتم استخدام اتصال علامات التبويب المخصّصة لإعداد CustomTabsSession بين التطبيق وعلامة التبويب في Chrome. نحتاج إلى الجلسة للتأكّد من أنّ التطبيق وتطبيق الويب ينتميان إلى المصدر نفسه. لا يتم إكمال عملية التحقّق إلا إذا تم إعداد روابط الأصول الرقمية بشكلٍ صحيح.

ننصحك بالاتصال بالرقم CustomTabsClient.warmup(). يسمح هذا الإعداد لتطبيق المتصفّح بإجراء عملية تهيئة مسبقة في الخلفية وتسريع عملية فتح عنوان URL.

// Set up a connection that warms up and validates a session.
CustomTabsServiceConnection connection = new CustomTabsServiceConnection() {
    @Override
    public void onCustomTabsServiceConnected(@NonNull ComponentName name, 
        @NonNull CustomTabsClient client) {
        // Create session after service connected.
        mSession = client.newSession(callback);
        client.warmup(0);
        // Validate the session as the same origin to allow cross origin headers.
        mSession.validateRelationship(CustomTabsService.RELATION_USE_AS_ORIGIN, 
            Uri.parse(url), null);
    }
    @Override
    public void onServiceDisconnected(ComponentName componentName) { }
};

إعداد دالة ردّ الاتصال التي تُطلق Intent بعد التحقّق من الصحة

تم تمرير CustomTabsCallback إلى الجلسة. نضبط onRelationshipValidationResult() في هذا التطبيق لتشغيل CustomTabsIntent الذي تم إنشاؤه سابقًا بعد نجاح عملية التحقّق من المصدر.

// Set up a callback that launches the intent after session validated.
CustomTabsCallback callback = new CustomTabsCallback() {
    @Override
    public void onRelationshipValidationResult(int relation, @NonNull Uri requestedOrigin, 
        boolean result, @Nullable Bundle extras) {
        // Launch custom tabs intent after session was validated as the same origin.
        CustomTabsIntent intent = constructExtraHeadersIntent(mSession);
        intent.launchUrl(MainActivity.this, Uri.parse(url));
    }
};

ربط خدمة علامات التبويب المخصّصة

يؤدي ربط الخدمة إلى تشغيلها وسيتم استدعاء onCustomTabsServiceConnected() للاتصال في النهاية. لا تنسَ إلغاء ربط الخدمة بشكلٍ مناسب. يتم الربط وإلغاء الربط بشكل شائع في طريقتَي مراحل النشاط onStart() وonStop().

// Bind the custom tabs service connection.
// Call this in onStart()
CustomTabsClient.bindCustomTabsService(this,
    CustomTabsClient.getPackageName(MainActivity.this, null), connection);

// …
// Unbind the custom tabs service.
// Call this in onStop().
unbindService(connection);

الرمز البرمجي للتطبيق التجريبي

يمكنك الاطّلاع على مزيد من التفاصيل حول "خدمة علامات التبويب المخصّصة" هنا. يمكنك الاطّلاع على مستودع android-browser-helper على GitHub للحصول على مثال عملي لتطبيق.

ملخّص

يوضّح هذا الدليل كيفية إضافة عناوين اختيارية إلى طلبات CORS في علامات التبويب المخصّصة، إذ يمكن إرفاق العناوين المدرَجة في قائمة الموافقة بكل طلب CORS في علامات التبويب المخصّصة. بشكل عام، تُعتبر العناوين غير المدرَجة في القائمة البيضاء غير آمنة في طلبات CORS، ويقوم Chrome بفلترتها تلقائيًا. ولا يُسمح بإرفاقها إلا للعملاء والخوادم من المصدر نفسه، والتي تم التحقّق منها باستخدام رابط أصول رقمية.