다른
출처
의 리소스를 사용하는 것을 제한하는 보안 방식
리소스에 접근하기 위해서 인증 토큰이 필요한 서버,
target.com
이 있다고 가정하자.해커는 사용자에게 서버의 리소스를 변조하는 스크립트가 담긴 링크,
hack.com
사용자에게 이메일 등으로 보내 피싱한다.사용자는 인증 토큰을 쿠키에 가지고 있는 상태에서
hack.com
링크를 클릭하게 된다면
target.com
의 리소스를 성공적으로 변조할 수 있을 것이다.
위 상황은 리소스를 가지고 있는 출처와 다른 출처에서 접근하는 상황이다.
SOP
는 이와 같은 상황을 방지하기 위해 나온 보안 방식이다.
CSRF
URL 구조에서
Protocol
,Host
,Port
를 합친 것을 말한다.즉, 이 세 요소가 같아야, 같은 출처(Same Origin)라고 볼 수 있는 것이다.
인터넷 상의
리소스 자원 그 자체
를 식별하는 문자열 시퀀스
URI 의 하위 개념으로 URL 과 URN 이 있다.
URI
=자원의 식별자
네트워크 상에서
리소스의 위치
를 나타내기 위한 규약이다.
URL
=자원의 위치
리소스에 이름을 부여하는 것을 말한다.
http://www.naver.com/index.html?page=1232950&id=776
를 살펴보자
http://www.naver.com/ 서버에 위치한 index.html 페이지는
query string인 page의 값에 따라 여러가지 화면 결과(자원)를 나타나게 된다.따라서
자원의 위치를 나타내는URL
은http://www.naver.com/index.html
까지가 되고
자원의 식별자를 나타내는URI
는http://www.naver.com/index.html?page=1232950&id=776
이 된다.
아래의 두 주소는 같은 URL 이면서 다른 URI 가 되는 것이다.
http://www.naver.com/index.html?page=1232950&id=776
http://www.naver.com/index.html?page=9923145&id=122
Q.
http://localhost
와 동일 출처인 것은?
1. https://localhost
2. http://locolhost:80
3. http://127.0.0.1
4. http://localhost/api/cors
Answer
2
,4
1
은 프로토콜이 다른다.
3
은 localhost의 ip 주소는 127.0.0.1 이니깐 맞긴하지만
브라우저에서 비교할때 String Value 로 비교를 해서 다른 출처라고 판단한다고 한다."localhost" == "127.0.0.1" ?? ->
False!!!
추가 HTTP 헤더를 사용하여
내 리소스를 다른 출처에서 접근이 가능하도록 권한을 부여하고
이를 브라우저에게 알려주는 체제이다.
OPTIONS
메서드를 통해 다른 도메인에 요청이 가능한지 확인하는 작업
요청이 가능하다는 응답을 받으면 그때 부터 실제 요청(ACTUAL REQUEST)을 보낸다.
위 그림은 preflight 요청을 보냈는데 권한이 없다고 응답이 온 경우이다.
Preflight Request
Origin
: 요청 출처Access-Control-Request-Method
: 실제 요청의 메서드Access-Control-Request-Headers
: 실제 요청의 추가헤더
Preflight Response
Access-Control-Allow-Origin
: 서버 측에서 허가한 다른 출처Access-Control-Allow-Methods
: 서버 측에서 허가한 메서드Access-Control-Headers
: 서버 측에서 허가한 헤더Access-Control-Max-Age
: Preflight 응답 캐시 시간,초단위
- 매번 Preflight 하는 것은 비효율적이기 때문에 빠른 요청을 위한 캐싱을 위함이다.
CORS 가 나타나기 이전에 만들어진 서버들은
SOP(Same origin policy) request만 가능하다는 전제하에 만들어졌다.CORS 가 나타나면서 보안적인 문제를 발생시킬 수 있게됐는데 이를 위함이다.
CORS 는 클라이언트에서만 나타나는 로그이다.
Preflight 가 없다면 허용하지 않은 다른 출처에서 서버의 리소스를 접근하는 요청을 보냈을 때
요청을 처리하면 안되는데 처리를 하고 CORS 관련 에러 상태 코드를 클라이언트로 보내게 된다.이러한 이유로 Preflight가 탄생하게 되었다.
Preflight 요청 없이 바로 요청을 보낸다.
Access-Control-Allow-Origin: *
은 와일드 카드로 모든 다른 출처를 허용한다는 뜻이다.조건
METHOD
:GET
,POST
,HEAD
만 가능Content-Type
:
application/x-www-form-urlencoded
|multipart/form-data
|text/plain
만 가능Header
:Accept
|Accept-Language
|Content-Language
|Content-Type
만 가능
인증 관련 헤더를 포함할때 사용하는 요청이다.
클라이언트 측
credentials: include
서버 측
Access-Control-Allow-Credentials : true
->Access-Control-Allow-Origin: *
과 같이 쓰면 에러가 발생한다.
프론트 단에서 프록시 서버 설정(개발 환경)
react 라이브러리(0.2.3 이상)를 사용하는 경우,
package.json 에"proxy": "http://localhost:8080"
를 추가한다.
직접 헤더 설정
서버에서 CORS 허용
CORS 정책을 설정해줄 Controller에
@CrossOrigin
어노테이션을 활용한다.
모든 것을 허용하려면 모든 컨트롤러에 어노테이션을 써야한다.