2020년 7월 26일

JWT ( JSON WEB TOKEN ) 인증환경에서 이미지 다운로드

서버 세션이 아닌 JWT 토큰을 기반으로 하는 웹 프로그램은 서버와의 통신이 필요하면 HTTP 헤더에 JWT 토큰을 포함하여  요청하고 서버는 클라이언트 요청 헤더의  JWT 토큰을 꺼내어 인증 정보를 꺼네어 사용하게 된다. 이미지의 경우는 어떻까 ? 

HTML 에서 img  태그는 JWT 와 같은 보안 토큰을 헤더에 포함하는 기능을 제공하지 않는다. 그러나 이미지 데이터를 스크립트에서 다운로드하고  data : image / FILETYPE; base64 URI 체계를 사용하여 이미지를 웹 페이지에 포함시키는 방법을 사용하면 간단하게 제한을 극복할 수 있다. ( vue-auth-image 모듈이나 관련 글들을 참고하는 것이 많은 도움이 되었다.) 



다수의 이미지를 다운로드 하는 경우 요청간 지연을 주기 위하여 아래와 같은 방법을 사용했다.
1
2
3
4
5
6
7
var delay = 600 ;
$("#grid figure img[is-secure]").each(function () {
  var $this = $(this);
  delay = delay + 50 ;
  $this.parent().addClass('is-loading');
  studio.ui.setSecureImage($this, delay);
});
이미지를 가져오지 못하는 경우에는 재요청을 수행하도록 코드하였다.
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
function setSecureImage(elemment, delay, callback) {
var delay = delay || 1000;
let url = elemment.attr("secure-image");
setImageAsBase64(
  url,
  function (data) {
    elemment.attr("src", data);
    elemment.parent().removeClass("is-loading");
    if (isFunction(callback)) callback();
  },
  function () {
    let maxRetry = 3,
      retry = 0;
    if (defined(elemment.data("max-retry"))) {
      maxRetry = elemment.data("max-retry");
    }
    if (defined(elemment.data("retry"))) {
      retry = elemment.data("retry");
    }
    if (retry < maxRetry) {
      elemment.data("retry", retry + 1);
      sleep(delay);
      setSecureImage(elemment);
    } else {
      elemment.parent().removeClass("is-loading");
    }
  }
);
}
 
async function setImageAsBase64(url, successHandler, errorHandler) {
const headers = {};
// JWT 토큰 값 설정
Object.assign(headers, studio.services.accounts.authHeader());
await axios
  .get(url, { headers: headers, responseType: "arraybuffer" })
  .then((response) => {
    var mineType = response.headers["content-type"].toLowerCase();
    var b64encoded = Buffer.from(response.data, "binary").toString("base64");
    var prefix = "data:" + mineType + ";base64,";
    if (isFunction(successHandler)) successHandler(prefix + b64encoded);
  })
  .then((error) => {
    if (isFunction(errorHandler)) errorHandler();
  });
}



아쉽지만 이미지를 다운로드하여 data 방식으로 설정하는데 있어 오류가 발생되어 다시 시도하도록 추가한 코드는 효용성이 없는 것 같다. 테스트 환경 이슈일 수도 있으나 다운로드에 있어 무작위로 오류가 발생하며 일단 오류가 발생되면 다시 시도한 경우 역시 오류가 발생한다. (→ 서버 이슈인지 코드 이슈인지는 확실하지 않다.)

참고자료

댓글 없음:

댓글 쓰기