개요
- 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" } }));