본문 바로가기

공부 자료/Spring

[Spring] CORS란? (CORS에 대해 알고 설정하기)

접근 시 발생하는 보안 이슈 CORS

 

CORS란?

 

CORS(Cross-Origin Resource Shargin)은 웹 애플리케이션에서

다른 도메인의 리소스에 접근할 때 발생하는 보안 이슈를 해결하기 위한 표준 방법이다.

즉, 정책을 위반해도 CORS 정책에 따른다면 다른 출처의 리소스라도 허용하게 해주는 것이다.

 

CORS 에러는 대부분 한 번씩 겪게 되는 일인데 이는 왜 생기는 것일까?

그 이유는 바로 HTTP 요청에 대해서 어떤 요청을 하는지에 따라 웹 브라우저마다 각기 다른 특징을 가지기 때문이다.

 


 

다른 출처와 같은 출처의 구분 기준은?

 

이를 구분하기 전에 '출처'가 무엇인지 먼저 알아야 한다.

 

출처(Origin)란?

출처는 우리가 작성하는 URL 중 Protocol + host + port를 의미힌다.

 

 

우리는 다른 도메인의 리소스에 접근할 때 CORS 에러가 발생한다고 하였는데, 이는 바로 SOP 때문이다.

 

SOP(Same-Origin Policy)란?

동일 출처 정책으로, 동일한 출처(Same-Origin)에서만 리소스를 공유할 수 있다는 것으로,

다른 출처(Cross-Origin) 서버에 있는 이미지 등의 리소스는 상호작용이 불가능하다.

 

 

여기까지 이해했다면 같은 출처와 다른 출처를 명확히 구분할 수 있는데,

이는 바로 Protocol + host + post가 동일하다면 같은 출처, 다르다면 다른 출처가 되는 것이다.

 

예를들어 http://localhost:8080 과 https://localhost:8080은 같은 출처일까?

아니다. Protocol이 http, https로 다르기 때문에 동일한 출처로 볼 수 없는 것이다.

 


 

CORS는 아래와 같은 방법으로 작동한다.

 

1. 브라우저는 HTTP 요청을 보낸다.

- 기본적으로 HTTP 프로토콜을 이용해 서버에 요청

- 브라우저는 요청 헤더에 Origin이라는 필드에 출처를 함께 담아서 보낸다.

 

2. 서버는 요청에 대한 응답을 반환한다.

- 서버는 요청에 대한 응답을 할 때 응답 헤더에 Access-Control-Allow-Origin이라는 필드를 추가하고 이 리소스를 접근하는 것이 허용된 출처 url을 내려보낸다.

 

3. 브라우저는 응답을 분석해 CORS 헤더를 확인한다.

- 응답을 받은 브라우저는 자신이 보낸 요청의 Origin과 서버가 보내준 응답의 Access-Control-Allow-Origin을 비교한다.

 

4. CORS 헤더가 존재하면 브라우저는 자원에 대한 권한을 검사한다.

- 응답이 유효한지 확인한다.

 

5. 권한이 허용되면 자원을 사용하고, 그렇지 않으면 에러가 발생한다.

- 만약 유효하지 않다면 그 응답을 사용하지 않고 버리게 되며, 이 때 CORS 에러가 발생한다.

 


 

 

CORS는 다른 도메인의 리소스에 접근하는데 있어 필수적인 보안 기능으로,

상황에 맞는 CORS 설정을 서버에서 진행(Access-Control-Allow-Origin 헤더에 허용할 출처를 기재해서 응답)해줘야 하며,

많은 설정을 할 경우 다른 보안 위험이 초래될 수 있기 때문에 최소한의 설정만 하는 것이 좋다.

 

 


 

Spring에서 CORS 설정하기

그렇다면 Spring에서는 CORS 설정을 어떻게 해줘야 할까?

방법은 아래와 같다.

 

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry){
       registry.addMapping("/**") // (1)
               .allowedOrigins("http://localhost:3000") // (2)
               .allowedMethods("GET", "POST", "PUT", "DELETE", "PATCH"); // (3)
               .allowCredentials(true) // (4)
               .maxAge(3000)
    }
}

// (5)
@Controller
@CrossOrigin(origins="*", methods = RequestMethod.GET)
public class AccountController{
	@GetMapping("/accountInfo/{id})
    @CrossOrigin(origins="*", methods = RequestMethod.GET)
    @ResponseBody
    public Account findId(){
    	return accountService.accountInfo(id);
    }

}

 

(1) addMapping("/**") : 허용할 경로를 설정하며,  / 이하의 모든 경로를 의미

 

(2) allowedOrigins : 허용할 출처 url

 

(3) allowedMethods : 기본적으로 POST/GET으로 설정되어 있으며, 허용할 HTTP Method를 작성

 

(4) allowCredentials : 쿠키 인증 요청 허용 여부

 

(5) @CrossOrigins : 특정 컨트롤러에만 CORS를 적용하고 싶은 경우 각각의 Contorller에 설정 가능