실전 프로젝트 마감이 거의 코앞까지 왔다
절체절명의 상황에서 당면한 위협에 관한 이야기
캔버스에 대한 수정 로직을 구현하던 중,
Uncaught DOMException: Failed to execute 'toDataURL' on
'HTMLCanvasElement': Tainted canvases may not be exported.
이러한 오류를 만났다.
직역하자면 캔버스가 오염됐으니 toDataURL 같은 메소드를 사용할 수 없다는 뜻.
귀엽게 그려낸 그림일기를 서버에 보내기 전에,
캔버스 이미지를 base64URL 로 받아 blob 데이터로 변환하고
blob 객체를 formData에 실어 보낸다.
이러한 로직은 일기를 작성할 때 뿐만 아니라 수정할 때도 똑같이 수행되는데
수정페이지에서는 서버에 저장된 이미지
를 캔버스의 배경으로 넣고
덧그림을 그리는 식으로 구현했다.
그런데 서버에 저장된 이미지를 캔버스의 배경으로 넣는 순간,
캔버스가 오염
되어 더이상 URL로 변환할 수 없는 상태가 되어버리는 것이다.
확인한 MDN의 내용은 다음과 같다.
교차 출처 이미지와 캔버스 허용하기
HTML은 이미지 처리를 위해 CORS header를 포함하고 있는 crossorigin 속성을 제공합니다. 이는
<img>
요소에서 정의된, 외부 origin으로 부터 가져오는 이미지가<canvas>
에서 사용할 수 있도록 해줍니다. 마치 현재 origin에서 가져온 것처럼 말입니다보안과 오염된 canvas들
다른 호스트들에 있는 이미지나 비디오를 포함한 canvas 비트맵의 픽셀들은 다양한 출처로 부터 가져오기 때문에, 보안과 관련된 문제를 피할 수 없습니다.
CORS를 통하지 않고, 다른 origin으로 부터 가져온 데이터들은 canvas에 그려지는 즉시 canvas는 오염됩니다. 오염된 canvas는 더 이상 안전하지 않은 것으로 여겨지고, canvas 이미지에서 데이터를 가져오려는 어떤 시도든 exception이 발생합니다.
만약 외부 출처 콘텐츠가 HTML
<img>
또는SVG
요소라면, canvas의 콘텐츠를 가져오려는 시도는 허용되지 않습니다.만약 외부 출처 콘텐츠가
HTMLCanvasElement
또는ImageBitMap
로부터 오는 이미지이고, 이미지의 source가 동일 출처 원칙과 맞지 않는다면 canvas의 콘텐츠를 읽으려는 시도는 막힙니다.
요약하자면, 이미지의 보안 관련 문제 때문에 CORS를 통하지 않고,
로컬환경이 아닌 곳에서 가져온 데이터를 canvas에 적용하면
canvas 가 오염되어 더이상 외부로 유출할 수 없다는 것이다.
이를 해결하기 위해서는,
클라이언트 측에서는 해당이미지의 crossOrigin 속성을 anonymous 로 변경해주고,
(이미지 경로 뒤에 캐시방지를 위한 파라미터를 추가함)
서버 측에서는 이미지가 저장된 주소(s3) 버킷 권한을 수정해 주어야 한다.
(CORS 권한 수정)
프로젝트의 거의 마지막 쯤 되어서 배경 화면도 추가되고
이것저것 손을 봤는데 너무 귀엽다. 마음에 든다.
🥰