API 간에 사용자 활성화를 일관되게 만들기

Mustaq Ahmed
Joe Medley
Joe Medley

악성 스크립트가 팝업과 같은 민감한 API를 악용하지 못하게 하려면 전체 화면 등에서 작동하며, 브라우저는 사용자를 통해 해당 API에 대한 액세스를 제어합니다. 활성화해야 합니다. 사용자 활성화는 사용자와 관련된 탐색 세션의 상태입니다. 사용자 액션: '활성' 상태는 일반적으로 사용자가 현재 페이지와 상호작용 중이거나 페이지 이후 상호작용을 완료한 사용자 있습니다. 사용자 동작은 같은 개념에 흔히 사용되지만 오해의 소지가 있는 용어입니다. 대상 예: 사용자의 스와이프 또는 획 돌리기 동작으로 페이지가 활성화되지 않아 스크립트 관점에서 사용자 활성화가 아닙니다.

오늘날 주요 브라우저에서는 사용자 활성화 방식이 크게 활성화 게이트 API를 제어합니다. Chrome에서는 토큰 기반 모델에서 일관된 모델을 정의하기에는 너무 복잡한 것으로 밝혀졌습니다. 모든 활성화 게이트 API에서의 동작을 제어합니다. 예를 들어 Chrome은 API를 통해 활성화 게이트 API에 대한 불완전한 액세스가 허용됨 postMessage()호출 setTimeout(); 사용자 활성화가 프로미스로 지원됨 XHR, 게임패드 상호작용 등입니다. 이러한 상호작용 중 일부는 아직 오래 지속된 버그입니다.

버전 72에서는 사용자가 활성화 제한이 있는 모든 API의 활성화 가용성이 완료되었습니다. 이렇게 하면 위에 언급된 일관성 및 MessageChannels)을 사용합니다. 사용자 활성화와 관련된 개발입니다. 또한 새로운 구현은 제안된 모바일 애플리케이션에 대한 새로운 사양 장기적으로 모든 브라우저를 하나로 모으는 것을 목표로 합니다.

사용자 활성화 v2는 어떻게 작동하나요?

새 API는 모든 window 객체에서 2비트 사용자 활성화 상태를 유지합니다. 이전 사용자 활성화 상태에 대한 고정 비트로, 프레임 계층 구조에서 현재 상태에 대한 일시적인 비트 (프레임에서 약 1초 후에 사용자가 활성화된 것으로 확인되는 경우) 고정 비트 은 설정된 후 프레임의 전체 기간 동안 재설정되지 않습니다. 임시 비트 모든 사용자 상호작용에 설정되며 만료 후 최소 1초 간격으로 또는 활성화를 소비하는 API 호출을 통해 (예: window.open())

여러 활성화 제어 API는 각각 다른 방식으로 사용자 활성화에 의존합니다. 방법 새 API는 이러한 API별 동작을 변경하지 않습니다. 예: window.open()가 이전과 마찬가지로 Navigator.prototype.vibrate()는 계속해서 프레임 (또는 그 서브프레임)이 사용자 행동을 본 적이 있다면 등등.

변경되는 사항

  • 사용자 활성화 v2는 사용자 활성화 가시성 개념을 공식화합니다. 특정 프레임과의 사용자 상호작용이 이제 활성 상태와 관계없이 포함된 모든 프레임 (및 해당 프레임만)을 출처입니다. (Chrome 72에는 가시성을 제공합니다 이 해결 방법은 할 수 있는 방법이 있습니다 사용자 활성화를 서브프레임에 명시적으로 전달합니다.
  • 활성화 제한 API가 활성화된 프레임에서 호출되지만 이벤트 핸들러 코드 외부에서 이벤트 핸들러에 있을 경우, 이벤트 핸들러는 사용자가 'active' 상태 (예: 만료되거나 소비되지 않은 콘텐츠) 사용자 이전 활성화 v2를 실행하면 무조건적으로 실패합니다.
  • 만료 시간 간격 퓨즈 내에 사용되지 않는 여러 사용자 상호작용 마지막 상호작용에 해당하는 단일 활성화로 변환합니다.

활성화 제한 API의 일관성 예시

다음은 팝업 창 (window.open()을 사용하여 열림)이 있는 두 가지 예입니다. 사용자 활성화 v2가 활성화 제한 API의 동작을 수행하는 방법 일관성이 있어야 합니다.

연결된 setTimeout() 호출

이 예제는 setTimeout() 데모를 참고하세요. click 핸들러가 1초 이내에 팝업을 열려고 하면 다음과 같습니다. 코드가 '구성'되는 방식과 관계없이 지연됩니다. 사용자 활성화 v2 충족 아래의 각 이벤트 핸들러는 click (100밀리초 지연):

function popupAfter100ms() {
  setTimeout(callWindowOpen, 100);
}

function asyncPopupAfter100ms() {
  setTimeout(popupAfter100ms, 0);
}

someButton.addEventListener('click', popupAfter100ms);
someButton.addEventListener('click', asyncPopupAfter100ms);

User Activation v2를 사용하지 않으면 두 번째 이벤트 핸들러가 Google의 모든 브라우저에서 있습니다 (첫 번째 규칙도 경우에 따라 다를 수 있습니다.)

교차 도메인 postMessage() 호출

이 예시에서는 postMessage() 데모를 참고하세요. 교차 출처 서브프레임의 click 핸들러가 메시지 2개를 직접 전송한다고 가정해 보겠습니다. 추가해야 합니다. 상위 프레임이 팝업을 열 수 있어야 함 두 메시지 중 하나를 수신할 수 있습니다.

// Parent frame code
window.addEventListener('message', e => {
  if (e.data === 'open_popup' && e.origin === child_origin)
    window.open('about:blank');
});

// Child frame code:
someButton.addEventListener('click', () => {
  parent.postMessage('hi_there', parent_origin);
  parent.postMessage('open_popup', parent_origin);
});

사용자 활성화 v2가 없으면 상위 프레임이 팝업을 수신할 때 팝업을 열 수 없음 두 번째 메시지입니다. 첫 번째 메시지도 '연결'된 경우 실패합니다. 다른 교차 출처 프레임 (첫 번째 수신자가 메시지를 전달하는 경우) 참조).

이 방법은 사용자 활성화 v2에서 원래 형식과 체이닝입니다.