개요

  • XHR (Xml Http Request, 이하 xhr)은 Ajax를 통한 비동기통신에서 자주 사용된다.
  • 다른 사이트(혹은 자기 자신의 사이트)로 요청을 보내고 받는 일을 주로 수행한다.
  • xhr 로 할 수 있는 것과 할 수 없는 것이 있다. (할 수 없는 것은 주로 보안과 관련된 제약사항이다.)
  • 이 페이지에서는 xhr로 할 수 있는 것, 할 수 없는 것을 정리한다.

할 수 없는 것 (보안제약사항)

크로스 도메인 요청에 대한 응답 읽기 (동일출처정책)

  • 일단 당연히 동일출처정책(SOP)은 제한을 받는다.
  • 즉, 다른 사이트로 요청을 보낼 수는 있어도 응답을 읽을 수 없다.
  • ※ CSRF공격은 요청을 보내기만 하면 되는 경우가 대부분이기 때문에 동일출처정책으로 CSRF 공격을 막을 수는 없다.

HTTP요청시 일부 헤더설정 불가

다음 헤더는 보안상 이유때문에 자바스크립트에서 HTTP요청을 보낼 때 사용할 수 없게 되어 있다. (이 헤더를 적용하도록 코드를 작성해도 브라우저가 무시해버린다.)

Accept-Charset
Accept-Encoding
Access-Control-Request-Headers
Access-Control-Request-Method
Connection
Content-Length
Cookie
Date
DNT
Expect
Host
Keep-Alive
Origin
Permissions-Policy
Proxy-*
Sec-*
Referer
TE
Trailer
Transfer-Encoding
Upgrade
Via

자세한내용은 아래 사이트를 참조한다.

  • https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/setRequestHeader
  • https://developer.mozilla.org/en-US/docs/Glossary/Forbidden_header_name

크로스 도메인 요청시 Authorization 헤더 설정 불가

  • Authorization 헤더는 HTTP요청에서 설정할 수 있지만, 크로스 도메인 요청이 되는 경우는 보안상 이유때문에 브라우저가 요청에서 삭제해버린다.
  • 즉, 동일 도메인 내의 요청에서만 사용할 수 있다.
  • https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/setRequestHeader

쿠키전송

  • xhr을 사용해서 쿠키전송도 할 수 없다. 위의 일부 헤더 설정이 안된다는 내용에서 Cookie헤더가 포함되어 있는 것과 동일한 내용이다. 그러나 중요하기 때문에 강조를 위해 한번 더 적어둔다.

참고: HTML 폼 전송시는 쿠키가 전송된다.

  • HTML 폼 전송시에는 쿠키가 전송된다.
  • 다만, 이 때는 쿠키의 SameSite 속성이 작동한다.
  • 쿠키에 SameSite 속성이 설정되어 있다면 해당 속성에 따라 쿠키를 함께 전송할지 말지를 브라우저가 결정한다.
  • 2020년 2월에 릴리즈한 Chrome 80버전부터는 SameSite속성이 없어도 lax인 것으로 간주하고 동작한다.
  • SameSite 속성의 값이 Strict이면 현재 사이트와 HTTP목적지 사이트가 동일 사이트일때만 해당 쿠키를 전송한다.
  • lax이면 다른 사이트여도 GET메서드라면 쿠키를 전송한다.
  • None이면 다른 사이트여도 해당 쿠키를 전송한다. 다만 None을 설정하고 싶은 경우는 최소한 HTTPS 통신에서만 쿠키가 전송되도록 secure 속성이 부여되어 있어야 한다.

할 수 있는 것

JSON 요청

  • xhr은 POST 엔드포인트에 대해 JSON 타입의 데이터 요청을 보낼 수 있다.
  • 출처: https://stackoverflow.com/questions/39519246/make-xmlhttprequest-post-using-json
  • 다만 이 경우는 Content-type이 application/json 로 간단한 요청이 아니기 때문에 프라플라이트 요청이 먼저 날아간다.
  • 따라서 요청을 받는 서버쪽에서 명시적으로 접근을 허용해주지 않는 이상 요청은 보낼 수 없다(CORS).
  • 참고로 동일한 오리진내에서의 요청인 경우에는 프리플라이트 요청은 발생하지 않는다.
var xmlhttp = new XMLHttpRequest();   // new HttpRequest instance 
var theUrl = "/json-handler";
xmlhttp.open("POST", theUrl);
xmlhttp.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xmlhttp.send(JSON.stringify({ "email": "hello@user.com", "response": { "name": "Tester" } }));