추가 HTTP 요청 헤더 추가

HTTP 요청에는 User-Agent 또는 Content-Type과 같은 헤더가 포함됩니다. 브라우저에서 연결한 헤더 외에도 Android 앱은 EXTRA_HEADERS 인텐트 추가를 통해 쿠키나 리퍼러와 같은 추가 헤더를 추가할 수 있습니다. 보안상의 이유로 Chrome은 인텐트가 실행되는 방식과 위치에 따라 일부 추가 헤더를 필터링합니다.

교차 출처 요청에는 클라이언트와 서버가 동일한 당사자가 소유하지 않으므로 추가 보안 레이어가 필요합니다. 이 가이드에서는 Chrome 맞춤 탭을 통한 이러한 요청 실행, 즉 브라우저 탭에서 URL을 여는 앱에서 실행된 인텐트를 설명합니다. Chrome 83까지는 개발자가 맞춤 탭을 실행할 때 모든 헤더를 추가할 수 있었습니다. 버전 83부터 Chrome은 승인 목록에 없는 헤더가 보안 위험을 야기하므로 승인 목록에 있는 교차 출처 헤더를 제외한 모든 헤더를 필터링하기 시작했습니다. Chrome 86부터 서버와 클라이언트가 디지털 애셋 링크를 사용하여 연결된 경우 교차 출처 요청에 승인 목록에 없는 헤더를 연결할 수 있습니다. 이 동작은 다음 표에 요약되어 있습니다.

Chrome 버전 CORS 헤더 허용됨
Chrome 83 이전 approvelisted, non-approvelisted
Chrome 83~85 승인 목록에 추가됨
Chrome 86 이상 디지털 애셋 링크가 설정된 경우 승인 목록, 비승인 목록

표 1. 승인 목록에 없는 CORS 헤더 필터링

이 도움말에서는 서버와 클라이언트 간에 확인된 연결을 설정하고 이를 사용하여 승인 목록에 있는 HTTP 헤더와 승인 목록에 없는 HTTP 헤더를 전송하는 방법을 설명합니다. 코드의 경우 맞춤 탭 인텐트에 추가 헤더 추가로 건너뛰어도 됩니다.

배경

승인 목록에 있는 CORS 요청 헤더와 승인 목록에 없는 CORS 요청 헤더

교차 출처 리소스 공유 (CORS)를 사용하면 한 출처의 웹 애플리케이션이 다른 출처의 리소스를 요청할 수 있습니다. CORS-approvelisted 헤더 목록은 HTML 표준에서 유지됩니다. 승인 목록에 포함된 헤더의 예는 다음 표에 나와 있습니다.

헤더 설명
accept-language 고객이 이해하는 자연어 광고
content-language 현재 잠재고객을 대상으로 하는 언어를 설명합니다.
content-type 리소스의 미디어 유형을 나타냅니다.

표 2: 승인 목록에 있는 CORS 헤더의 예

승인 목록에 있는 헤더는 민감한 사용자 정보가 포함되어 있지 않고 서버가 손상을 줄 수 있는 작업을 실행할 가능성이 낮기 때문에 안전하다고 간주됩니다.

승인되지 않은 헤더의 예는 다음 표에 나와 있습니다.

헤더 설명
bearer-token 서버에서 클라이언트를 인증합니다.
출처 요청 출처를 나타냅니다.
쿠키 서버에서 설정한 쿠키가 들어 있습니다.

표 3.: 승인 목록에 없는 CORS 헤더의 예시

승인 목록에 없는 헤더를 CORS 요청에 연결하는 것은 HTML 표준에서 권장하지 않으며 서버는 교차 출처 요청에 승인 목록에 있는 헤더만 포함되어 있다고 가정합니다. 교차 출처 도메인에서 승인되지 않은 헤더를 전송하면 악성 서드 파티 앱에서 Chrome (또는 다른 브라우저)이 저장하고 요청에 첨부하는 사용자 쿠키를 오용하는 헤더를 만들 수 있습니다. 쿠키를 사용하면 그렇지 않은 경우 불가능한 악성 서버 트랜잭션을 인증할 수 있습니다.

맞춤 탭 요청에 CORS 승인 목록 헤더 연결

맞춤 탭은 맞춤설정된 브라우저 탭에서 웹페이지를 실행하는 특별한 방법입니다. CustomTabsIntent.Builder()를 사용하여 맞춤 탭 인텐트를 만들 수 있습니다. Browser.EXTRA_HEADERS 플래그와 함께 Bundle를 사용하여 이러한 인텐트에 헤더를 연결할 수도 있습니다.

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

Google에서는 언제든지 승인 목록에 있는 헤더를 맞춤 탭 CORS 요청에 연결할 수 있습니다. 하지만 Chrome은 기본적으로 승인되지 않은 헤더를 필터링합니다. 다른 브라우저의 동작은 다를 수 있지만 개발자는 일반적으로 승인 목록에 없는 헤더가 차단될 것으로 예상해야 합니다.

맞춤 탭에 승인되지 않은 헤더를 포함하는 데 지원되는 방법은 먼저 디지털 액세스 링크를 사용하여 교차 출처 연결을 확인하는 것입니다. 다음 섹션에서는 이를 설정하고 필요한 헤더와 함께 맞춤 탭 인텐트를 실행하는 방법을 보여줍니다.

맞춤 탭 인텐트에 추가 헤더 추가

승인 목록에 없는 헤더가 맞춤 탭 인텐트를 통해 전달되도록 하려면 Android 애플리케이션과 웹 애플리케이션 간에 디지털 애셋 링크를 설정하여 작성자가 두 애플리케이션을 모두 소유하고 있는지 확인해야 합니다.

공식 가이드에 따라 디지털 애셋 링크를 설정하세요. 링크 관계의 경우 링크가 확인되면 두 앱이 모두 동일한 출처에 속함을 나타내는 'delegate_permission/common.use_as_origin'을 사용합니다.

추가 헤더가 있는 맞춤 탭 인텐트 만들기

맞춤 탭 인텐트를 만드는 방법에는 여러 가지가 있습니다. 빌드 종속 항목에 라이브러리를 추가하여 AndroidX에서 제공되는 빌더를 사용할 수 있습니다.

MULTI_LINE_CODE_PLACEHOLDER_1

인텐트를 빌드하고 추가 헤더를 추가합니다.

MULTI_LINE_CODE_PLACEHOLDER_2

맞춤 탭 연결은 앱과 Chrome 탭 간에 CustomTabsSession를 설정하는 데 사용됩니다. 앱과 웹 앱이 동일한 출처에 속하는지 확인하려면 세션이 필요합니다. 디지털 애셋 링크가 올바르게 설정된 경우에만 인증이 통과됩니다.

CustomTabsClient.warmup()를 호출하는 것이 좋습니다. 이를 통해 브라우저 애플리케이션이 백그라운드에서 사전 초기화하고 URL 열기 프로세스의 속도를 높일 수 있습니다.

MULTI_LINE_CODE_PLACEHOLDER_3

유효성 검사 후 인텐트를 실행하는 콜백 설정

CustomTabsCallback가 세션에 전달되었습니다. 출처 확인에 성공하면 이전에 만든 CustomTabsIntent를 실행하도록 onRelationshipValidationResult()를 설정합니다.

MULTI_LINE_CODE_PLACEHOLDER_4

맞춤 탭 서비스 연결 바인딩

서비스를 바인딩하면 서비스가 실행되고 연결의 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에서 기본적으로 필터링합니다. 디지털 저작물 링크로 확인된 동일한 출처의 클라이언트와 서버에만 첨부할 수 있습니다.