생각만 해도 눈물이 나는 CORS 에러..
다들 한번쯤은 봤을 것이다.,.,
💀 Access to fetch at ‘https://localhost/post’ from origin ‘http://localhost:8080’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. If an opaque response serves your needs, set the request’s mode to ‘no-cors’ to fetch the resource with CORS disabled.
이 에러를 처음 접했을 때 해결하려고 찾아보니까,
에러 메세지엔 헤더에 Access-Control 어쩌구를 넣으라는데
그게 뭔데요 ㅠ ㅠ,,
검색을 통해 이해해보려고 했지만 ... 도대체 무슨 말인지 도통 알 수가 없었다. ^_ㅠ
요청 출처가 다르면 발생하는 에러라고 두루뭉술하게 이해하고 있었는데
이번 기회에 확실하게 정리해보았다.
🌈 우아한 Tech 테코톡
🌳 나봄님의 CORS 영상을 보며 작성한 글입니다.
- 진짜 세상에서 제일 쉽게 설명해주시니까 꼬옥 영상으로 보시길
SOP 🤔
- Same Origin Policy
다른 출처의 리소스를 사용하는 것에 제한을 두는 보안 방식을 의미한다.
즉, 출처가 같을 때만 리소스를 주고 받을 수 있도록 하는 정책이다.
프로토콜
, 호스트
, 포트
로 정의된다.
출처: 🌳 나봄님의 CORS
프로토콜
은 https, 호스트
는 github.com, 포트는 :443
이다.http://localhost
와 동일 출처인 url은 몇 번일까 🧐https://localhost
http://localhost:80
http://127.0.0.1
http://localhost/api/cors
1번은 프로토콜이 다르니까 다른 출처,
2번은 생략된 80번 포트번호를 적은 url이니까 동일 출처,
3번은 호스트가 다르니 다른 출처,
4번은 같은 출처에 path를 덧붙인 경우니까 동일 출처!
출처: 🌳 나봄님의 CORS
아래의 상황을 가정해보자
1. 페이스북 서비스를 이용하는 유저가 로그인을 해서 유저 인증 토큰을 받아왔다.
2. 해커가 유저에게 자신이 만든 사이트로 이동하게끔 하는 메일을 보낸다.
3. 해커가 만든 사이트엔 페이스북에 글을 작성하게 하는 스크립트가 담겨있다.
4. 유저가 메일을 클릭하면?
유저가 메일을 클릭하면 해커가 만든 사이트로 이동하게 되고,
해커는 유저의 인증 토큰을 사용해서 페이스북에 글을 작성하도록 스크립트를 실행시킨다.
이 때 페이스북은 서비스 요청이 들어온 출처를 확인해본다.
페이스북은 해당 출처가 자신의 출처와 다르기 때문에,
즉 Cross Origin에 해당하기 때문에 SOP에 위반된다고 판단한다!
- Cross-Origin Resource Sharing
추가 HTTP 헤더를 사용해 한 출처에서 실행중인 웹 어플리케이션이 다른 출처의 자원에 접근할 수 있는 권한을 브라우저에게 알려주는 체제이다.다른 출처
에 있는 자원에 접근 +접근 권한을 브라우저에게
알려준다는 것에 초점을 맞추자
본 요청을 보내기 전에 서버에게 요청을 보내도 되는지 확인 받는 작업을 프리플라이트라고 한다.
이 때 OPTIONS 메소드를 통해 요청을 보낸다.
만약 사전 요청에서 가능하다는 응답을 받으면, 그 때 본 요청을 보낸다.
프로젝트를 하면서 도대체 프리플라이트가 뭔데 요청하지도 않은 OPTIONS 메소드가 뜨는지 정말정말 궁금했다
출처: 🌳 나봄님의 CORS
프리플라이트 한 줄 요약 = 사전 확인 작업
프리플라이트 세 줄 요약
"너 CORS 아니? 대비해놨니?"
라고 물어보는 매커니즘
출처: 🌳 나봄님의 CORS
사전 요청없이 바로 본 요청을 보내면서, 그 즉시 Cross-Origin인지 확인하는 절차다.
Access-Control-Allow-Origin = '요청 도메인'
을 담아 브라우저에게 허용했다고 알려야 한다.Simple request는 아래의 조건을 만족해야 한다.
Accept
, Accept-Language
,Content-Language
, Content-Type
application/x-www-form-urlencoded
,multipart/form-data
,text/plain
인증 관련 헤더를 포함할 때 사용하는 요청으로
쿠키나 JWT 같은 토큰을 클라이언트에서 서버로 보내고 싶을 때 사용하는 요청이다.
이 요청을 하려면 아래의 설정을 해줘야 한다.
credentials : include
Access-Control-Allow-Credentials : true
위에서 어떤 상황에 CORS 에러가 발생하는지 알았으니 해결방법을 알아보자
Allow CORS
를 설치한 뒤, 설정을 토글시키면 에러가 감쪽같이 사라진다.
출처: 🌳 나봄님의 CORS
// vue.config.js
module.exports = {
devServer: {
Proxy: {
‘/api’ : {
target: ‘http://localhost:8080',
changeOrigin: true,
}
}
}
}
http-proxy-middleware
라이브러리를 사용하면 된다.Const {createProxyMiddleware} = require(“http-proxy-middleware”)
module.exports = function(app) {
app.use(
“/api”, createProxyMiddleware({
Target: “http://localhost:5000”,
changeOrigin: true,
})
)
}
출처 : [나를 너무 힘들게 했던 CORS 에러 해결하기]
Access-Control-Allow-Origin = '요청 도메인'
코드를 작성해 보내는 방법이다.@CrossOrigin
어노테이션 설정@CrossOrigin(origins = (허가할 도메인))
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsConfiguration implements WebMvcConfigurer{
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api")
.allowedOrigins("허가할 도메인");
}
}
CORS 때문에 날린 시간만 합쳐도 이틀은 될 것 같다.
그동안 머리 속에 엉켜있었던 지식을 풀어서 쓰니 정리가 확실하게 된 것 같다.
이제는 CORS 에러가 발생해도 문제 없다!!! ㉻㉻
추후에 또 좋은 방법을 찾게 되면 계속 수정하면서 추가해봐야 겠다.