HTTP-запросы содержат такие заголовки, как User-Agent или Content-Type. Помимо заголовков, добавляемых браузерами, приложения Android могут добавлять дополнительные заголовки, такие как Cookie или Referrer, через дополнительный параметр Intent EXTRA_HEADERS . В целях безопасности Chrome фильтрует некоторые из дополнительных заголовков в зависимости от того, как и где запускается Intent.
Cross-origin requests require an additional layer of security as the client and server are not owned by the same party. This guide discusses launching such requests through Chrome custom tabs , ie intents launched from apps that open a URL in the browser tab. Until Chrome 83, developers could add any headers when launching a Custom Tab. From version 83 onward, Chrome started filtering all except approvelisted cross-origin headers, since non-approvelisted headers posed a security risk. Starting with Chrome 86, it is possible to attach non-approvelisted headers to cross-origin requests, when the server and client are related using a digital asset link . This behaviour is summarised in the following table:
| версия для Chrome | Заголовки CORS разрешены |
|---|---|
| до Chrome 83 | одобренные, не одобренные |
| Chrome 83 — Chrome 85 | утвержденный список |
| начиная с Chrome 86. | При установлении связи с цифровым активом, активы попадают в список одобренных или не попадают в него. |
Таблица 1: Фильтрация заголовков CORS, не включенных в список одобренных.
В этой статье показано, как установить проверенное соединение между сервером и клиентом и использовать его для отправки HTTP-заголовков, содержащих как одобренные, так и неодобренные данные. Код можно найти в разделе «Добавление дополнительных заголовков в пользовательские интенты вкладок» .
Фон
Заголовки запроса CORS для одобренных и неодобренных пользователей
Протокол CORS (Cross-Origin Resource Sharing) позволяет веб-приложению из одного источника запрашивать ресурсы из другого источника. Список заголовков , разрешенных CORS, хранится в стандарте HTML . Примеры разрешенных заголовков приведены в следующей таблице:
| Заголовок | Описание |
|---|---|
| accept-language | рекламирует естественные языки, которые понимает клиент. |
| язык контента | описывает язык, предназначенный для современной аудитории. |
| тип содержимого | указывает тип носителя информации для ресурса. |
Таблица 2: Примеры утвержденных заголовков CORS.
Заголовки, включенные в список одобренных, считаются безопасными, поскольку они не содержат конфиденциальной информации о пользователях и вряд ли приведут к выполнению сервером потенциально опасных операций.
Примеры заголовков, не включенных в список одобренных, приведены в следующей таблице:
| Заголовок | Описание |
|---|---|
| токен предъявителя | аутентифицирует клиента на сервере |
| источник | указывает на источник запроса |
| печенье | содержит файлы cookie, установленные сервером. |
Таблица 3: Примеры заголовков CORS, не включенных в список одобренных.
Attaching non-approvelisted headers to CORS requests is discouraged by the HTML standard and servers assume that cross-origin requests contain only approvelisted headers. Sending non-approvelisted headers from cross-origin domains would allow malicious third-party apps to craft headers that misuse user cookies that Chrome (or another browser) stores and attaches to requests. The cookies could authenticate malicious server transactions that would otherwise not be possible.
Добавление заголовков CORS approvedlisted к запросам на пользовательских вкладках.
Пользовательские вкладки — это особый способ запуска веб-страниц в настраиваемой вкладке браузера. Интенты для пользовательских вкладок можно создавать с помощью 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"));
Мы всегда можем добавлять заголовки approvedlisted к запросам CORS для пользовательских вкладок. Однако Chrome по умолчанию фильтрует заголовки, не включенные в список одобренных. Хотя в других браузерах поведение может отличаться, разработчикам следует ожидать, что заголовки, не включенные в список одобренных, будут блокироваться в целом.
Поддерживаемый способ включения заголовков, не включенных в список одобренных, в пользовательские вкладки — это предварительная проверка междоменного соединения с использованием цифровой ссылки доступа. В следующем разделе показано, как настроить эти параметры и запустить интент «Пользовательские вкладки» с необходимыми заголовками.
Добавление дополнительных заголовков к пользовательским интентам вкладок
Настройте ссылки на цифровые активы.
Для того чтобы разрешить передачу заголовков, не включенных в список одобренных, через интенты Custom Tab, необходимо установить связь между цифровыми активами 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;
}
Настройте подключение пользовательских вкладок для проверки связи с активом.
Соединение Custom Tabs используется для настройки сессии 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 для пользовательских вкладок. Заголовки approvedlisted можно добавлять к каждому запросу CORS для пользовательских вкладок. Заголовки non-approvelisted обычно считаются небезопасными в запросах CORS, и Chrome фильтрует их по умолчанию. Добавление таких заголовков разрешено только для клиентов и серверов одного происхождения, подтвержденных ссылкой на цифровой актив.