درخواستهای HTTP حاوی هدرهایی مانند User-Agent یا Content-Type هستند. جدا از هدرهایی که توسط مرورگرها پیوست میشوند، برنامههای اندروید ممکن است هدرهای اضافی مانند Cookie یا Referrer را از طریق EXTRA_HEADERS Intent extra اضافه کنند. به دلایل امنیتی، کروم بسته به نحوه و محل اجرای یک intent، برخی از هدرهای اضافی را فیلتر میکند.
درخواستهای بین مبدایی به یک لایه امنیتی اضافی نیاز دارند زیرا کلاینت و سرور متعلق به یک طرف نیستند. این راهنما در مورد راهاندازی چنین درخواستهایی از طریق تبهای سفارشی کروم، یعنی اهداف راهاندازی شده از برنامههایی که یک URL را در تب مرورگر باز میکنند، بحث میکند. تا کروم ۸۳، توسعهدهندگان میتوانستند هنگام راهاندازی یک تب سفارشی، هر هدری را اضافه کنند. از نسخه ۸۳ به بعد، کروم شروع به فیلتر کردن همه هدرهای بین مبدایی به جز هدرهای تایید شده کرد ، زیرا هدرهای تایید نشده یک خطر امنیتی ایجاد میکردند. با شروع کروم ۸۶، میتوان هدرهای تایید نشده را به درخواستهای بین مبدایی پیوست کرد، زمانی که سرور و کلاینت با استفاده از یک لینک دارایی دیجیتال به هم مرتبط هستند. این رفتار در جدول زیر خلاصه شده است:
| نسخه کروم | هدرهای CORS مجاز هستند |
|---|---|
| قبل از کروم ۸۳ | تایید شده، تایید نشده |
| کروم ۸۳ تا کروم ۸۵ | تایید شده |
| از کروم ۸۶ به بعد | تأیید شده، تأیید نشده هنگام راهاندازی پیوند دارایی دیجیتال |
جدول ۱: فیلتر کردن هدرهای CORS تایید نشده.
این مقاله نحوهی ایجاد یک اتصال تأیید شده بین سرور و کلاینت و استفاده از آن برای ارسال هدرهای http تأیید شده و همچنین تأیید نشده را نشان میدهد. برای کد میتوانید از بخش افزودن هدرهای اضافی به تبهای سفارشی صرف نظر کنید.
پیشینه
هدرهای درخواست CORS تایید شده در مقابل تایید نشده
اشتراکگذاری منابع بین مبدایی (CORS) به یک برنامه وب از یک مبدا اجازه میدهد تا منابعی از مبدا دیگر را درخواست کند. فهرست هدرهای تأیید شده توسط CORS در استاندارد HTML نگهداری میشود. نمونههایی از هدرهای تأیید شده در جدول بعدی نشان داده شده است:
| سربرگ | توضیحات |
|---|---|
| زبان پذیرش | زبانهای طبیعی قابل فهم برای مشتری را تبلیغ میکند |
| زبان محتوا | زبانی را توصیف میکند که برای مخاطب فعلی در نظر گرفته شده است |
| نوع محتوا | نوع رسانه منبع را نشان میدهد |
جدول ۲: نمونهای از سربرگهای CORS تایید شده.
هدرهای تأیید شده ایمن در نظر گرفته میشوند زیرا حاوی اطلاعات حساس کاربر نیستند و بعید است که باعث شوند سرور عملیات بالقوه مخربی انجام دهد.
نمونههایی از سربرگهای تأیید نشده در جدول زیر نشان داده شده است:
| سربرگ | توضیحات |
|---|---|
| توکن حامل | کلاینت را در سرور احراز هویت میکند |
| منشأ | نشان دهنده مبدا درخواست است |
| کوکی | حاوی کوکیهای تنظیمشده توسط سرور است |
جدول ۳: نمونهای از هدرهای CORS تایید نشده در فهرست.
استاندارد HTML، اتصال هدرهای تایید نشده به درخواستهای CORS را توصیه نمیکند و سرورها فرض میکنند که درخواستهای بین مبدایی فقط حاوی هدرهای تایید شده هستند. ارسال هدرهای تایید نشده از دامنههای بین مبدایی به برنامههای شخص ثالث مخرب اجازه میدهد تا هدرهایی را بسازند که از کوکیهای کاربر که کروم (یا مرورگر دیگری) ذخیره کرده و به درخواستها متصل میکند، سوءاستفاده میکنند. کوکیها میتوانند تراکنشهای مخرب سرور را که در غیر این صورت امکانپذیر نبودند، تأیید کنند.
اتصال هدرهای تایید شده 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 تبهای سفارشی پیوست کنیم. با این حال، کروم به طور پیشفرض هدرهای تایید نشده را فیلتر میکند. اگرچه مرورگرهای دیگر ممکن است رفتار متفاوتی داشته باشند، اما توسعهدهندگان باید انتظار داشته باشند که هدرهای تایید نشده به طور کلی مسدود شوند.
روش پشتیبانیشده برای گنجاندن هدرهای تأییدنشده در تبهای سفارشی، ابتدا تأیید اتصال متقابل با استفاده از یک لینک دسترسی دیجیتال است. بخش بعدی نحوه تنظیم این موارد و راهاندازی یک هدف تبهای سفارشی با هدرهای مورد نیاز را نشان میدهد.
افزودن سربرگهای اضافی به تبهای سفارشی
پیوندهای دارایی دیجیتال را تنظیم کنید
برای اینکه هدرهای تایید نشده بتوانند از طریق Custom Tab intents منتقل شوند، لازم است یک لینک دارایی دیجیتال بین برنامه اندروید و وب ایجاد شود که تأیید کند نویسنده هر دو برنامه را در اختیار دارد.
برای تنظیم لینک دارایی دیجیتال، راهنمای رسمی را دنبال کنید. برای رابطه لینک از "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;
}
برای اعتبارسنجی لینک دارایی، یک اتصال تب سفارشی تنظیم کنید
یک اتصال Custom Tabs برای تنظیم CustomTabsSession بین برنامه و تب کروم استفاده میشود. ما به این session نیاز داریم تا تأیید کنیم که برنامه و برنامه وب متعلق به یک مبدا هستند. این تأیید فقط در صورتی انجام میشود که لینکهای دارایی دیجیتال به درستی تنظیم شده باشند.
توصیه میشود که 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 به session ارسال شد. ما 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 مراجعه کنید.
خلاصه
این راهنما نحوه اضافه کردن هدرهای دلخواه به درخواستهای CORS تبهای سفارشی را نشان داد. هدرهای تایید شده میتوانند به هر درخواست CORS تبهای سفارشی پیوست شوند. هدرهای تایید نشده معمولاً در درخواستهای CORS ناامن تلقی میشوند و کروم به طور پیشفرض آنها را فیلتر میکند. پیوست کردن آنها فقط برای کلاینتها و سرورهایی با مبدا یکسان مجاز است که توسط یک لینک دارایی دیجیتال تأیید شدهاند.