여기까지 보았을 때는, CORS고 SOP고 그냥 다른 origin이더라도 자유롭게 리소스 요청을 하면 되지 않나?라고 생각 들 수도 있다.
하지만 클라이언트 어플리케이션은 사용자의 공격에 너무나도 취약하기 때문에(웹 어플리케이션은 소스코드가 개발자 도구같은곳에 노출되어 있으므로), 악의를 가진 사용자가
CSRF(Cross Site Request Forgery) 혹은 XSS(Cross Site Scripting)공격을 할 수 있기 때문에,
그에 대비하기 위함이다.
Cross Origin, 즉 다른 출처인지 파악하는 로직이 서버에 구현된 것이 아닌, 웹 브라우저에만 구현되어 있는 스펙이라고 한다.
따라서 CORS를 위반하더라도, 서버는 Origin을 굳이 파악하지 않으므로 정상적으로 리소스를 반환하지만 웹 브라우저에서는 CORS를 위반의 결과로 응답이 나왔다고 판단할 수 있으므로, 정상적으로 나온 응답을 버려 버린다.
Origin
헤더에 요청을 보내는 곳의 정보를 담고 서버로 요청을 보낸다.Access-Control-Allow-Origin
헤더에 다음과 같은 허용 유무 정보를 담아 보낸다Access-Control-Allow-Origin: *
(와일드 카드) → 전체 origin에 대해서 리소스 접근을 허용한다.Access-Control-Allow-Origin: <origin>
→ 특정 origin(꺽새괄호 안의 url)에 대해서만 접근을 허용한다.Access-Control-Allow-Origin: null
→ 접근을 허용하지 않는다.출처 : http://wiki.gurubee.net/display/SWDEV/CORS+(Cross-Origin+Resource+Sharing)
본격적인 교차 출처 HTTP 요청 전(preflight)에 서버 측에서 그 요청의 메서드와 헤더에 대해 인식하고 있는지를 확인하는 CORS 요청. HTTP메소드는 GET, POST 등이 아닌 OPTIONS
를 이용한다.
장점
단점
GET, HEAD, POST메소드에 대해서만 가능한 요청이다.
요청 자체가 CSRF등으로부터 안전할 것이라고 가정한다.
다른 도메인 API서버에서 자신을 인증하여 정상적인 응답을 받기 위해 쿠키를 통한 인증을 한다.
클라이언트와 서버 각각에서 해야 하는 작업이 있는데,
클라이언트 : 요청을 credentials 모드로 설정한다.
서버 : 응답헤더를 Access-Control-Allow-Crendentials: true
로 설정한다
주의할 점
Access-Control-Allow-Origin: *
과 Access-Control-Allow-Credentials: true는
함께 사용할 수 없다.Access-Control-Allow-Credentials: true를 사용하는 경우는 사용자 인증이 필요한 리소스 접근이 필요한 경우인데, 만약 Access-Control-Allow-Origin: *를 허용한다면 CSRF 공격에 매우 취약해져 악의적인 사용자가 인증이 필요한 리소스를 마음대로 접근할 수 있기 때문에, 정책상으로 아예 동작하지 않도록 막아버린 것입니다.
따라서 Access-Contorl-Allow-Credentials: true
인 경우에는 반드시 Access-Control-Allow-Origin의 값이 하나의 origin 값으로 명시되어 있어야 정상적으로 동작합니다.
doFilter
메소드에서 OPTIONS
HTTP 메소드 요청 시 반환할 헤더들을 정의한다. (ex : Access-Control-Allow-Origin, Access-Control-Allow-Credentials 등)@CrossOrigin
어노테이션의 옵션으로 허용할 origin을 설정해 준다.Config
클래스에서 WebMvcConfigurer
를 Bean으로 등록한 후, 허용할 origin을 추가한다.