افزودن سرصفحه‌های درخواست اچ‌تی‌تی‌پی اضافی

درخواست‌های HTTP حاوی سرصفحه‌هایی مانند User-Agent یا Content-Type هستند. علاوه‌بر سرایندهای پیوست‌شده توسط مرورگرها، برنامه‌های Android ممکن است سرایندهای اضافی، مانند «کوکی» یا «ارجاع‌دهنده» را ازطریق EXTRA_HEADERS Intent extra اضافه کنند. به‌دلایل امنیتی، Chrome برخی‌از سرصفحه‌های اضافی را بسته به نحوه و مکان راه‌اندازی هدف فیلتر می‌کند.

درخواست‌های میان‌مبدئی به لایه امنیتی بیشتری نیاز دارند زیرا کارخواه و سرور متعلق به یک طرف نیستند. این راهنما درباره راه‌اندازی چنین درخواست‌هایی ازطریق برگه‌های سفارشی Chrome بحث می‌کند، یعنی هدف‌هایی که از برنامه‌هایی راه‌اندازی می‌شوند که نشانی وب را در برگه مرورگر باز می‌کنند. تا Chrome نسخه ۸۳، توسعه‌دهندگان می‌توانستند هنگام راه‌اندازی «برگه سفارشی» هر سرصفحه‌ای را اضافه کنند. از نسخه ۸۳ به بعد، Chrome شروع به فیلتر کردن همه سرصفحه‌های میان‌مبدئی به‌جز سرصفحه‌های موجود در فهرست تأیید کرد، زیرا سرصفحه‌هایی که در فهرست تأیید نبودند خطر امنیتی ایجاد می‌کردند. از Chrome 86، وقتی سرور و کارخواه بااستفاده از پیوند دارایی دیجیتال مرتبط باشند، می‌توان سرصفحه‌هایی را که در فهرست تأیید نیستند به درخواست‌های میان‌مبدئی پیوست کرد. این رفتار در جدول زیر خلاصه شده است:

نسخه Chrome سرایندهای CORS مجاز
قبل‌از Chrome 83 در فهرست تأییدشده، در فهرست تأییدنشده
Chrome 83 تا Chrome 85 در فهرست تأییدشده
از Chrome 86 به بعد وقتی پیوند دارایی دیجیتال راه‌اندازی شده باشد، در فهرست تأییدشده‌ها، در فهرست تأییدشده‌ها نیست

جدول ۱.: فیلتر کردن سرصفحه‌های CORS که در فهرست تأیید نیستند.

این مقاله نشان می‌دهد که چگونه یک اتصال تأییدشده بین سرور و کلاینت راه‌اندازی کنید و از آن برای ارسال سرایندهای http فهرست مجاز و غیرمجاز استفاده کنید. برای کد می‌توانید به افزودن سرصفحه‌های اضافی به هدف‌های برگه سفارشی بروید.

پس‌زمینه

سرایندهای درخواست CORS فهرست تأییدشده درمقابل فهرست تأییدنشده

هم‌رسانی منبع میان‌مبدئی (CORS) به برنامه وب از یک مبدأ اجازه می‌دهد منابع مبدأ دیگری را درخواست کند. فهرست سرایندهای تأییدشده CORS در استاندارد HTML نگهداری می‌شود. نمونه سرصفحه‌های موجود در فهرست مجاز در جدول بعدی نشان داده شده است:

سرصفحه شرح
accept-language زبان‌های طبیعی را که کارخواه متوجه می‌شود تبلیغ می‌کند
زبان محتوا زبان درنظرگرفته‌شده برای مخاطب فعلی را توصیف می‌کند
نوع محتوا نوع رسانه منبع را نشان می‌دهد

جدول ۲.: نمونه سرایندهای CORS در فهرست مجاز.

سرایندهای موجود در فهرست مجاز ایمن درنظر گرفته می‌شوند زیرا حاوی اطلاعات حساس کاربر نیستند و احتمال اینکه باعث شوند سرور عملیات بالقوه مخرب انجام دهد کم است.

نمونه‌هایی از سرصفحه‌هایی که در فهرست تأیید نیستند در جدول زیر نشان داده شده است:

سرصفحه شرح
رمزیاب دارنده اصالت‌سنجی کارخواه در سرور
منشأ نشان‌دهنده منشأ درخواست است
کوکی حاوی کوکی‌های تنظیم‌شده توسط سرور است

جدول ۳.: نمونه سرایندهای 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` استفاده کنید که نشان می‌دهد هر دو برنامه پس‌از تأیید پیوند به یک مبدأ تعلق دارند.

ایجاد کردن هدف برگه سفارشی با سرصفحه‌های اضافی

روش‌های متعددی برای ایجاد هدف «برگه‌های سفارشی» وجود دارد. می‌توانید از سازنده موجود در 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() تماس بگیرید. این ویژگی به برنامه مرورگر اجازه می‌دهد در پس‌زمینه پیش‌مقداردهی شود و فرایند باز کردن نشانی وب را تسریع کند.

// 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) { }
};

راه‌اندازی Callback که قصد را پس‌از اعتبارسنجی راه‌اندازی می‌کند

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);

کد برنامه نمایشی

جزئیات بیشتر درباره «سرویس برگه‌های سفارشی» را می‌توانید در اینجا ببینید. برای دیدن نمونه برنامه درحال کار، مخزن GitHub android-browser-helper را ببینید.

خلاصه

این راهنما نحوه افزودن سرصفحه‌های دلخواه به درخواست‌های CORS برگه‌های سفارشی را نشان می‌دهد. سرصفحه‌های موجود در فهرست تأییدشده‌ها را می‌توان به هر درخواست CORS برگه‌های سفارشی پیوست کرد. سرایندهای غیرمجاز عموماً در درخواست‌های CORS ناامن درنظر گرفته می‌شوند و Chrome به‌طور پیش‌فرض آن‌ها را فیلتر می‌کند. پیوست کردن آن‌ها فقط برای کارخواه‌ها و سرورهای دارای منبع یکسان که با پیوند دارایی دیجیتال تأیید شده‌اند مجاز است.