접근 시 발생하는 보안 이슈 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에 설정 가능
'공부 자료 > Spring' 카테고리의 다른 글
[Spring JPA] 페이징 Pageable, Page, Slice / 페이지 나누기 (2) | 2023.11.21 |
---|---|
[Spring] Getter/Setter를 지양하자? (1) | 2023.11.21 |
[Spring Boot] ResponseEntity란? (0) | 2023.11.20 |
[MyBatis/Spring] About @Mapper/@Repository (0) | 2023.11.13 |
[Springframework] Naver API를 이용한 회원가입 및 로그인 (1) | 2023.11.11 |