CORS

cornpip
|2023. 7. 20. 12:07

CORS (Cross-Origin-Resource Sharing)

URL

domain name = root name + TLD

https://blog.cornpip.store 과 같이 포토를 명시하지 않을 경우 https는 https://blog.cornpip.store:443 과 동일하게 동작하고

http://blog.cornpip.storehttp://blog.cornpip.store:80 과 같게 동작한다.

CORS는 Cross-Origin-Resource Sharing 으로 다른 Origin에서 자원을 공유할 때와 관련돼 있다.

그럼 Origin(출처)이란? 호스트 + 포트 번호를 의미한다.

( CORS 의 존재는 기본적으로 브라우저는 Same-Origin Policy 를 권한다고 볼 수 있다. )

 

CORS는 경우에 따라 3가지 작동 방식이 존재한다.

A. 예비 요청 (Preflight Request)

  1. 브라우저는 요청을 바로 보내지않고 OPTIONS Method로 예비 요청을 보낸다.
  2. 서버는 Access-Control-Allow-Origin/Methods/Headers,
    Access-Control-Max-Age( 해당 예비 요청이 브라우저에 캐시 될 수 있는 시간을 초단위로 설정 )
    등의 정보를 헤더에 담아 브라우저에 보낸다.
  3. 브라우저는 보낸 예비 요청과 응답받은 서버의 정책을 비교하고 안전한 요청이라면 본 요청을 보낸다.

(1) XMLHttpRequest( 본 요청 ) 전에 preflight가 보내지는 것을 볼 수 있다.
(2) OPTIONS 메서드와 응답 헤더에서 정책 정보를 볼 수 있다.

(2)의 이미지에서 서버의 Cors 설정은 다음과 같다.

(code1)
    	configuration.setAllowedOrigins(Arrays.asList("http://localhost:4000"));
        configuration.setAllowedMethods(Arrays.asList("*"));
        configuration.setAllowedHeaders(Arrays.asList("*"));
        configuration.setAllowCredentials(true);
        configuration.addExposedHeader(JwtUtil.AUTHORIZATION_HEADER);

(2)의 응답에서 Headers는 딱히 정보가 안보인다.

Method 와일드 카드는 preflight 요청의 메서드에 대해 허용된 메서드인지만 알려주는 것 같다. 설정은 전부 허용인데 요청 메서드에 맞게 응답 가능한 메서드만 알려준다. (GET 요청을 보내면 Allow-Headers에 GET으로 나온다.)

 

네트워크에서 preflight가 꼭 먼저 찍히는 건 아니고 preflight가 허용되지 않으면 본 요청은 pending 상태에서 실패로 반환된다.

 

언뜻 생각해보면 예비 요청이 성능에 영향을 미칠 수 있어보인다.

그래서 Access-Control-Max-Age 옵션이 있다. 예비 요청에 대한 응답은 Access-Control-Max-Age 옵션을 통해 브라우저에 캐싱될 수 있으며 캐싱됐다면 예비 요청의 응답을 서버가 아닌 캐시에서 받아온다.

B. 단순 요청 (Simple Request)

예비 요청을 보내지 않고 바로 본 요청을 보낸 후 서버의 응답에서 Access-Control-Allow-Origin 를 확인하고 적절한 CORS 인지 검사한다.

단순 요청으로 동작하기 위해선 몇가지 조건이 필요하고 대부분은 조건이 만족되지 않고 예비 요청으로 동작한다.

C. 인증된 요청 (Credentialed Request)

인증된 요청의 흐름은 예비 요청과 같게 동작하고 거기에 추가 설정이 필요하다.

기본적으로 브라우저에 저장된 정보는 별도 옵션없이 요청에 담아서 전송할 수 없다. 그래서 credentials option 옵션이 필요하다.

  • same-origin - 같은 출처 간 요청에만 인증 정보를 담음
  • include - 모든 요청에 인증 정보를 담음
  • omit - 모든 요청에 인증 정보를 담지않음

옵션은 위와 같은 선택지가 있다. axios의 withCredentials: true 는 include와 같게 동작한다.

서버에도 예비 요청과는 다른 추가 설정이 필요하다.

  1. Access-Control-Allow-Credentials = true
  2. Access-Control-Allow-Origin 에 와일드카드 문자(*)는 사용할 수 없다.
  3. Access-Control-Allow-Methods/Headers 에도 와일드카드 문자(*)는 사용할 수 없다?
    code1 에서 보았듯이 Methods와 Headers에 와일드카드 문자를 사용해도 에러가 발생하진 않았다.
    *_기능적으로 동작하지 않는 부분은 있을 수도 있다. ( 의심해보자 )
    *_1과 2의 규칙은 설정하지 않으면 에러를 발생한다.

참조

https://inpa.tistory.com/entry/WEB-%F0%9F%93%9A-CORS-%F0%9F%92%AF-%EC%A0%95%EB%A6%AC-%ED%95%B4%EA%B2%B0-%EB%B0%A9%EB%B2%95-%F0%9F%91%8F

 

🌐 악명 높은 CORS 개념 & 해결법 - 정리 끝판왕 👏

악명 높은 CORS 에러 메세지 웹 개발을 하다보면 반드시 마주치는 멍멍 같은 에러가 바로 CORS 이다. 웹 개발의 신입 신고식이라고 할 정도로, CORS는 누구나 한 번 정도는 겪게 된다고 해도 과언이

inpa.tistory.com

 

'Web' 카테고리의 다른 글

HTTP 메서드 GET/POST 차이  (0) 2023.09.06
OAuth2 를 알아보자  (0) 2023.07.25
쿠키(cookie), 서버 <-> 클라이언트 set-cookie 에러 사항들  (0) 2023.07.21