티스토리 뷰

실무 이슈

HTMLMediaElement.playbackRate 조작이슈

알 수 없는 사용자 2021. 8. 16. 17:06

0. 시작


이전까지는 jwplayer 버전에 따른 원인 분석과 해결방법을 알아보았다면,
이제는 jwplayer 버전은 유지하고, 추가 소스코드로만 해결할 수 있는 방법에 대한 생각을 정리할 것이다.

배속 이벤트 이슈

  1. 크롬 확장프로그램으로 비디오 조절기능을 사용시 배속 임의 조작
  2. HTMLMediaElement.playbackRate 클라이언트(브라우저 관리자 도구) 조작

1. 원인


구글링을 하던 도중 관리자도구에서 비디오의 속성값을 임의로 변경하여 클라이언트가 배속을 임의로 설정하는 경우를 발견하였다.

document.getElementById("video").querySelector("video").playbackRate = 10

이 외에도 크롬 확장프로그램에서 배속을 바꿀시 소스에 걸린 이벤트가 정상적으로 동작하지 않고 있었다.
이 부분은 jwplayer의 버전 문제인지는 모르겠지만, 위처럼 로우레벨(?)에서 클라이언트가 속성값 자체를 변경할 시 어떻게 대처해야할까에 대해 고민했다.

2. 해결


video태그에서 배속을 정하는 값은 아래 링크의 공식문서와 같다.
(https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/playbackRate)
아마 jwplayer이벤트에서도 결국엔 해당 값을 변경하는 것으로 배속을 제어할 것이라 생각했고, 이 값이 의도치않게 변경되는 것을 감지 및 방지하는 것에 대해 생각했다.

내가 생각한 방법은 자바스크립트의 프로퍼티 타입 정의 함수이다.
(https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty).

본 글은 함수에 대한 내용을 다루기 위한 내용은 아니기 떄문에, 간력히 설명하면 속성에 값을 대입하거나 읽을 때, 특정 로직이 실행되게 하는 get,set를 정의할 수 있고, 프로퍼티 값을 변경유무 등을 설정할 수 있는 함수이다.

프로퍼티 설정 중 set에 로직을 별도로 정의하여, 몇 배속까지 사용할 수 있는지를 설정하였다.

// 배속조절 막기

// 변경 불가능하게 const 처리
const maxPlayBackRate = 5;
document.addEventListener("DOMContentLoaded", function(){
  var originalDescriptor = Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, 'playbackRate');

  Object.defineProperty(HTMLVideoElement.prototype,'playbackRate',{
    set:function(value){
      if(value > maxPlayBackRate) {
        console.log( maxPlayBackRate + "보다 커서 적용안함")
        return;
      } 
      originalDescriptor.set.call(this,value);
    },
    get:originalDescriptor.get
  });

})

샘플 코드로 maxPlayBackRate이상의 배속설정 값이 들어오면 설정되지 않도록 하는 코드이다.
테스트를 위해 클라이언트에서 값을 임의로 조정하면 아래와 같이 출력되는 것을 확인할 수 있다.

보통 이렇게 처리를 하면, 클라이언트에서 임의로 바꿔도 시스템에서 허용가능한 범위까지만 배속을 설정할 수 있게 하는 것이기 때문에 상관없다.
하지만, 특수한 경우에 클라이언트 관리자모드에서는 동작하지 않고, 실제 소스동작에서만 작동해야하는 경우가 있다면 caller를 통해서 가능할 것 같다.

const maxPlayBackRate = 5;
document.addEventListener("DOMContentLoaded", function(){
  var originalDescriptor = Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, 'playbackRate');

  Object.defineProperty(HTMLVideoElement.prototype,'playbackRate',{
    set:function(value){
      console.log("caller name : " + arguments.callee.caller.name); // 호출 함수 체크
      if(value > maxPlayBackRate) {
        console.log( maxPlayBackRate + "보다 커서 적용안함")
        return;
      } 
      originalDescriptor.set.call(this,value);
    },
    get:originalDescriptor.get
  });

})

function changePlayBackRate(speed) {
  document.querySelector('video').playbackRate = speed;
}

위 코드를 보면 알겠지만, 배속을 바꿀 수 있는 함수를 별도로 정의하고, playbackRate를 변경할 때 어디서 호출했는지 체크할 수 있다.

console.log("caller name : " + arguments.callee.caller.name); // 호출 함수 체크
  1. changePlayBackRate 함수 호출 시

  2. 관리자도구에서 속성 값 변경 시

  3. jwplayer onReady 이벤트 시

    jwplayer('video').onReady(function() { document.querySelector('video').playbackRate = 3; })

물론 관리자도구에서 변경했다는 함수 이름이 없다는 것이기 때문에, 함수가 아닌 곳에서 진짜 호출했을 수도 있다.
이 부분만 잘 체크하여 사용한다면 혹시 모를 케이스에 대해서도 보장되는 안정적인 시스템이 구축될 것 같다.

+) Object.defineProperty에 대해 찾아보면 알겠지만, 이 함수자체를 관리자도구에서 재정의하더라도 configurable 옵션떄문에 클라이언트가 재정의할 수 없다.

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함