programing

JWT 기반 인증으로 파일 다운로드 처리 방법

newnotes 2023. 3. 11. 09:27
반응형

JWT 기반 인증으로 파일 다운로드 처리 방법

저는 Angular에서 인증을 JWT 토큰으로 처리하는 웹 앱을 쓰고 있습니다. 즉, 모든 요청에는 필요한 모든 정보가 포함된 "인증" 헤더가 있습니다.

이 방법은 REST 호출에 적합하지만 백엔드에서 호스트되는 파일의 다운로드 링크를 처리하는 방법을 이해할 수 없습니다(파일은 웹 서비스가 호스트되는 서버에 있습니다).

수 .<a href='...'/>링크는 헤더를 전송하지 않기 때문에 인증에 실패합니다., 하다, 하다, 하다, 하다, 하다, 하다, 하다, 하다, 하다, 하다, 하다, 하다, 하다, 하다, 하다, 하다, 하다, 하다, 하다, 하다, 하다, 하다, 하다, 하다, 하다, 하다, 하다, 하다.window.open(...).

제가 생각한 솔루션:

  1. 서버에 임시 보안 보호되지 않은 다운로드 링크를 생성합니다.
  2. 인증정보를 URL 파라미터로 전달하여 수동으로 케이스 처리
  3. XHR을 통해 데이터를 가져와 파일 클라이언트 측을 저장합니다.

위의 사항들은 모두 만족스럽지 못하다.

지금 사용하고 있는 솔루션은 1개입니다.저는 두 가지 이유로 이것이 마음에 들지 않습니다.첫 번째는 이상적인 보안은 아니지만 특히 서버에서 많은 작업이 필요합니다.새로운 "랜덤" URL을 생성하여 (아마도 DB에) 저장했다가 클라이언트에 반환하는 서비스를 다운로드해야 합니다.클라이언트는 URL을 가져와 window.open 또는 이와 유사한 기능을 사용합니다.요청 시 새 URL이 여전히 유효한지 확인한 후 데이터를 반환해야 합니다.

적어도 2개는 할 일이 많은 것 같다.

3은 사용 가능한 라이브러리를 사용하더라도 많은 작업이 필요한 것으로 보이며 잠재적인 문제가 많습니다.(다운로드 상태 바를 제공하여 파일 전체를 메모리에 로드한 후 사용자에게 로컬로 저장하도록 요청해야 합니다).

하지만 그 작업은 꽤 기본적인 것 같아서, 더 간단한 것이 없을까 생각하고 있습니다.

나는 반드시 "앵귤러 방식"의 해결책을 찾고 있는 것은 아니다.일반 Javascript로도 괜찮습니다.

다운로드 속성, fetch API 및 URL.createObject사용하여 클라이언트에 다운로드하는 방법은 다음과 같습니다.URL. JWT를 사용하여 파일을 가져오고, 페이로드를 BLOB로 변환하고, BLOB를 객체에 넣습니다.URL, 앵커 태그의 소스를 해당 개체로 설정합니다.URL 및 해당 개체를 클릭합니다.javascript URL 입니다.

let anchor = document.createElement("a");
document.body.appendChild(anchor);
let file = 'https://www.example.com/some-file.pdf';

let headers = new Headers();
headers.append('Authorization', 'Bearer MY-TOKEN');

fetch(file, { headers })
    .then(response => response.blob())
    .then(blobby => {
        let objectUrl = window.URL.createObjectURL(blobby);

        anchor.href = objectUrl;
        anchor.download = 'some-file.pdf';
        anchor.click();

        window.URL.revokeObjectURL(objectUrl);
    });

의 값download속성은 최종 파일 이름이 됩니다.필요에 따라서, 다른 응답의 설명에 따라서, 컨텐츠 디스포지션 응답 헤더로부터 목적의 파일명을 마이닝 할 수 있습니다.

기술.

JWT 에반젤리스트로 알려진 Auth0의 마티아스 월로스키의 조언을 바탕으로 Hawk와 서명 요청을 생성하여 해결했습니다.

Woloski 인용:

예를 들어 AWS와 같이 서명된 요청을 생성하는 방법으로 이 문제를 해결할 수 있습니다.

여기에서는 액티베이션링크에 사용되는 이 기술의 예를 나타냅니다.

백엔드

다운로드 URL에 서명하기 위한 API를 만들었습니다.

요청:

POST /api/sign
Content-Type: application/json
Authorization: Bearer...
{"url": "https://path.to/protected.file"}

응답:

{"url": "https://path.to/protected.file?bewit=NTUzMDYzZTQ2NDYxNzQwMGFlMDMwMDAwXDE0NTU2MzU5OThcZDBIeEplRHJLVVFRWTY0OWFFZUVEaGpMOWJlVTk2czA0cmN6UU4zZndTOD1c"}

서명된 URL로 파일을 얻을 수 있습니다.

요청:

GET https://path.to/protected.file?bewit=NTUzMDYzZTQ2NDYxNzQwMGFlMDMwMDAwXDE0NTU2MzU5OThcZDBIeEplRHJLVVFRWTY0OWFFZUVEaGpMOWJlVTk2czA0cmN6UU4zZndTOD1c

응답:

Content-Type: multipart/mixed; charset="UTF-8"
Content-Disposition': attachment; filename=protected.file
{BLOB}

(조용지에 의해) 프런트 엔드

이렇게 하면 한 번의 사용자 클릭으로 모든 작업을 수행할 수 있습니다.

function clickedOnDownloadButton() {

  postToSignWithAuthorizationHeader({
    url: 'https://path.to/protected.file'
  }).then(function(signed) {
    window.location = signed.url;
  });

}

기존 "fetch/create ObjectURL" 및 "download-token" 접근법 대신 새로운 창을 대상으로 하는 표준 Form POST가 있습니다.브라우저가 서버 응답의 첨부 파일 헤더를 읽으면 새 탭을 닫고 다운로드를 시작합니다.이 방법은 PDF와 같은 리소스를 새 탭에 표시하는 경우에도 잘 작동합니다.

이를 통해 이전 브라우저에 대한 지원이 향상되어 새로운 유형의 토큰을 관리할 필요가 없어집니다.또한 URL의 사용자 이름/비밀번호 지원은 브라우저에 의해 삭제되므로 URL의 기본 인증보다 장기적인 지원이 더 좋습니다.

클라이언트 측에서는target="_blank"SPA(Single Page App)입니다.

주요 주의사항은 서버측 JWT 검증에서는 헤더가 아닌 POST 데이터로부터 토큰을 취득해야 한다는 것입니다.프레임워크가 Authentication 헤더를 사용하여 루트 핸들러에 대한 접근을 자동으로 관리하는 경우 적절한 인가를 위해 JWT를 수동으로 검증할 수 있도록 핸들러를 인증되지 않은/익명으로 마킹해야 할 수 있습니다.

폼을 동적으로 작성하고 즉시 파기하여 적절하게 정리할 수 있습니다(주의: 이는 플레인 JS로 실행할 수 있지만 JQuery는 명확성을 위해 여기서 사용됩니다).

function DownloadWithJwtViaFormPost(url, id, token) {
    var jwtInput = $('<input type="hidden" name="jwtToken">').val(token);
    var idInput = $('<input type="hidden" name="id">').val(id);
    $('<form method="post" target="_blank"></form>')
                .attr("action", url)
                .append(jwtInput)
                .append(idInput)
                .appendTo('body')
                .submit()
                .remove();
}

숨겨진 입력으로 제출해야 하는 추가 데이터를 추가하고 양식에 추가되었는지 확인하십시오.

James의 답변의 순수 JS 버전

function downloadFile (url, token) {
    let form = document.createElement('form')
    form.method = 'post'
    form.target = '_blank'
    form.action = url
    form.innerHTML = '<input type="hidden" name="jwtToken" value="' + token + '">'

    console.log('form:', form)

    document.body.appendChild(form)
    form.submit()
    document.body.removeChild(form)
}

다운로드용 토큰을 생성합니다.

각도 내에서 인증된 요청을 작성하여 임시 토큰을 얻은 후(예를 들어 1시간) get 파라미터로 URL에 추가합니다.이렇게 하면 원하는 방식으로 파일을 다운로드할 수 있습니다(window.open...).

언급URL : https://stackoverflow.com/questions/29452031/how-to-handle-file-downloads-with-jwt-based-authentication

반응형