μ΄μ ν¬μ€ν μμλ νλ‘ νΈ μλ²μ λ°± μλ²κ° HTTPS λ‘ ν΅μ νλλ‘ Apache μλ²μ SSL μΈμ¦μλ₯Ό μ€μΉνκ³ , 리λ²μ€ νλ‘μ μ€μ μΌλ‘ μ€νλ§ λΆνΈ μ ν리μΌμ΄μ μ μμ²μ΄ μ λ¬λλλ‘ λ§λ€μλ€. μ΄λ‘ μΈν΄ νΌν© μ½ν μΈ μ€λ₯λ ν΄κ²°νμ§λ§, CORS μ€λ₯κ° μλ‘κ² λ°μνλ€.
π©π»βπ» μλ¬ μμΈ μ°ΎκΈ°
1λ¨κ³ : CORS μ μ± λ³κ²½
μ μΌ μ²μμΌλ‘ μ€νλ§ λΆνΈ CORS μ μ± μμ addAllowedOrigin μ€μ μ μ€μ νλ‘ νΈ μλ²μ λλ©μΈμΌλ‘ λ³κ²½νλ€. κ·Έλ¬λ μ¬μ ν CORS μ€λ₯κ° λ°μνλλ°β¦ λκ° μ΄μνλ€.
config.addAllowedOrigin("https://www.ncbt.site");
preflight request λΌλ μ©μ΄κ° μ κ²½μ°μ¬μ μ°Ύμ보λ, CORS κ° λμνλ λ°©μμ μμ²μ λ°λΌ λ¬λΌμ§λ€κ³ νλ€.
μ’ λ₯ | λ©μλ | Content-Type |
---|---|---|
Simple Request | GET, POST, HEAD | text/plain, application/x-www-form-urlencoded, multipart/form-data |
Preflight Request | Simple Request κ° μλ κ²½μ°κ° ν΄λΉνλ€ | Β |
λ¨μ μμ²μ΄ μλ κ²½μ°, λΈλΌμ°μ λ μμ²μ ν λ²μ 보λ΄μ§ μκ³ μ¬μ μμ²κ³Ό λ³Έ μμ²μΌλ‘ λλμ΄ μλ²μ μ μ‘νλ€κ³ νκ³ μ΄ λμ μμ²μ΄ Preflight Request κ° λλ κ²μ΄λ€. μ΄ κ²½μ° OPTIONS λ©μλλ₯Ό μ¬μ©νλ€κ³ νλ€.
λλ GET μμ²μ 보λμ§λ§ Content-Type μ application/json μΌλ‘ μμ²νκΈ°μ Preflight Request λ‘ μμ²λ λ― νλ€. κ·Έλμ μλ μ€μ μ μΆκ°νμ§λ§ μ¬μ ν ν΄κ²°λμ§ μμλ€.
// OPTIONS λ©μλ μΆκ°
config.addAllowedMethod("OPTIONS");
2λ¨κ³ : μλ¬ λ‘κ·Έ νμΈ
μ¬μ ν κ°μ΄ μ€μ§ μμμ μ€νλ§ μλ¬ λ‘κ·Έλ₯Ό νμΈν΄ 보μλλ HTTP request header λ₯Ό νμ±νλ κ³Όμ μμ μ€λ₯κ° λ°μν κ² κ°μλ€.
2025-01-04T04:20:41.214Z INFO 1 --- [backend] [io-8080-exec-10] o.apache.coyote.http11.Http11Processor : Error parsing HTTP request header
Note: further occurrences of HTTP request parsing errors will be logged at DEBUG level.
java.lang.IllegalArgumentException: Invalid character found in method name [0x050x010x00...]. HTTP method names must be tokens
at org.apache.coyote.http11.Http11InputBuffer.parseRequestLine(Http11InputBuffer.java:407) ~[tomcat-embed-core-10.1.28.jar!/:na]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:257) ~[tomcat-embed-core-10.1.28.jar!/:na]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) ~[tomcat-embed-core-10.1.28.jar!/:na]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:904) ~[tomcat-embed-core-10.1.28.jar!/:na]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1741) ~[tomcat-embed-core-10.1.28.jar!/:na]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) ~[tomcat-embed-core-10.1.28.jar!/:na]
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1190) ~[tomcat-embed-core-10.1.28.jar!/:na]
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-10.1.28.jar!/:na]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63) ~[tomcat-embed-core-10.1.28.jar!/:na]
at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na]
μ°Ύμ보λ 리λ²μ€ νλ‘μλ‘ μμ²μ μ λ¬νλ κ³Όμ μμ μμ²μ μμ νκ±°λ μμμν¬ μ μλ€κ³ νμ¬ μνμΉ μλ²μ μλ¬ λ‘κ·Έλ νμΈν΄λ³΄μλ€.
# Apache μλ²λ‘ λ€μ΄μ€λ λͺ¨λ μμ² νμΈ
tail -f /var/log/apache2/access.log
# μΆλ ₯λ λ‘κ·Έ
122.35.170.152 - - [04/Jan/2025:13:08:48 +0900] "OPTIONS /refreshToken HTTP/1.1" 403 4180 "https://www.ncbt.site/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"
18.191.32.67 - - [04/Jan/2025:13:11:47 +0900] "\x16\x03\x01" 400 483 "-" "-"
122.35.170.152 - - [04/Jan/2025:13:12:28 +0900] "OPTIONS /refreshToken HTTP/1.1" 403 1021 "https://www.ncbt.site/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"
122.35.170.152 - - [04/Jan/2025:13:12:40 +0900] "OPTIONS /refreshToken HTTP/1.1" 403 1021 "https://www.ncbt.site/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"
18.191.32.67 - - [04/Jan/2025:13:12:47 +0900] "GET / HTTP/1.1" 301 513 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) Chrome/126.0.0.0 Safari/537.36"
122.35.170.152 - - [04/Jan/2025:13:12:50 +0900] "OPTIONS /refreshToken HTTP/1.1" 403 1021 "https://www.ncbt.site/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"
122.35.170.152 - - [04/Jan/2025:13:12:50 +0900] "OPTIONS /ranking/v2 HTTP/1.1" 403 489 "https://www.ncbt.site/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"
122.35.170.152 - - [04/Jan/2025:13:22:43 +0900] "OPTIONS /refreshToken HTTP/1.1" 403 4180 "https://www.ncbt.site/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"
122.35.170.152 - - [04/Jan/2025:13:22:52 +0900] "GET /form/email-code?email=hwy9597%40naver.com HTTP/1.1" 403 999 "https://www.ncbt.site/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"
λ΄κ° λ³΄λΈ λͺ¨λ μμ²μ΄ Apache μλ²μμ 403 μλ¬λ‘ λ°νλλ κ²μ νμΈνλ€. μκ°ν΄λ³΄λ©΄ ν΄λΌμ΄μΈνΈμ μμ²μ΄ μΌλ¨ Apache μλ²λ‘ λ€μ΄κ°κ³ , Apache κ° μ€νλ§μΌλ‘ 리λ²μ€ νλ‘μ ν΄μ£Όλ κ²μ΄κΈ° λλ¬Έμβ¦ Apache μμλ CORS ν€λλ₯Ό μΆκ°ν΄μΌκ² λ€ μΆμλ€.
π ν΄κ²°
1λ¨κ³ : Apache μμ CORS μ€μ
# VirtualHost μ€μ νμΌ μ΄κΈ°
vi /etc/apache2/sites-available/000-default.conf
# VirtualHost :*443 λΈλμ μλ μ½λ μΆκ°
<VirtualHost *:443>
ServerAdmin yeonguo95@gmail.com # μλ² μλ¬μ μ¬μ©μμκ² μλ΄λ μ΄λ©μΌ
DocumentRoot /var/www/html # μ΄κ±΄ κ·Έλλ‘ λ
λκΈ°
ServerName api.ncbt.site # μλ² λλ©μΈ
# 리λ²μ€ νλ‘μ κ΄λ ¨ μ€μ
ProxyRequests Off
ProxyPreserveHost On
# Apache μ λλ ν 리 κΆν λΆμ¬
<Directory /var/www/html>
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
<Directory /var/www>
Require all granted
</Directory>
# CORS ν€λ μΆκ°
<IfModule mod_headers.c>
Header always set Access-Control-Allow-Origin "https://www.ncbt.site"
Header always set Access-Control-Allow-Methods "OPTIONS, GET, POST, PUT, DELETE"
Header always set Access-Control-Allow-Headers "Authorization, Content-Type, X-Custom-Header, Set-Cookie"
Header always set Access-Control-Allow-Credentials "true"
Header always set Access-Control-Expose-Headers "Authorization, Set-Cookie"
</IfModule>
# 리λ²μ€ νλ‘μ νμ±ν
<IfModule mod_proxy.c>
ProxyPreserveHost On
ProxyPass / http://localhost:8080/
ProxyPassReverse / http://localhost:8080/
</IfModule>
# ν리νλΌμ΄νΈ OPTIONS μμ² μ²λ¦¬
RewriteEngine On
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ $1 [R=200,L]
</VirtualHost>
# κ΄λ ¨ λͺ¨λ νμ±ν
sudo a2enmod headers
sudo a2enmod rewrite
sudo a2enmod proxy
sudo a2enmod proxy_http
# μνμΉ μ¬μμ
sudo systemctl restart apache2
μ΄ν λ€μ μλν΄λ³΄λ, μ€λ₯ λ©μμ§κ° μ‘°κΈ λ³νλ€. Access-Control-Allow-Origin ν€λμ λ€μ€κ°μ΄ λ€μ΄κ°λ€λ κ²β¦
2λ¨κ³ : Spring CORS μ€μ μμ
μ ν€λμ λ€μ€κ°μ΄ λ€μ΄κ°κΉ? μκ°ν΄λ³΄λ μ°λ¦¬λ Spring μλ²μ λ°λ‘ ν΅μ νλ κ²μ΄ μλ, λ‘λλ°Έλ°μ μν μ Apache μλ²μ ν΅μ νκ³ μλ€. κ·Έλ¬λ―λ‘ CORS μ€μ μ Apache μβλ§β ν΄μ£Όκ³ , Spring μͺ½μ CORS μ€μ μ μμ ν΄μΌ νλ κ²μ΄λ€. κ·Έλμ κ΄λ ¨ μ€μ μ μ λΆ μ£Όμ μ²λ¦¬νλ€.
3λ¨κ³ : Docker μ€ν 맀컀λμ¦ λ³κ²½
κ³μ μ§ννμμλ CORS μλ¬κ° κ³μ λ°μνλ€. κ·Έλμ λ²λ© λ μκ°μ΄β¦ λ컀 νλΈμ λ¬Έμ κ° μλκΉ? μΆμλ€. μλνλ©΄ μμ²μ΄ λ€μ΄κ°λ€λ©΄ λΆλͺ μ€νλ§ μ»¨ν μ΄λμ λ‘κ·Έκ° λ°ν λ° μ무κ²λ λ¨μ§ μλ κ²μ΄λ€. νΉμλΌλ μμ λ²μ μ μ½λκ° κ°±μ λμ§ μκ³ μλ κ² μλκ° μΆμλ€. (νΉν λ컀 νλΈμμλ μ½λλ₯Ό μ΄ν΄λ³Ό μκ° μμ΄μ λ³κ²½μ¬νμ΄ λ°μλμλμ§ μκΈ° μ΄λ ΅λ€)
κ·Έλμ κ²°κ΅ Github λ₯Ό μ¬μ©ν΄μ 컨ν μ΄λλ₯Ό μ€νμν€κΈ°λ‘ νλ€.
# 3-1. (λ‘컬PCμμ) μμ€μ½λλ₯Ό κΉνλΈμ νΈμ
git push origin main
# 3-2. (ν΄λΌμ°λμμ) μμ€μ½λ λ΄λ €λ°κΈ°
git pull origin main
# 3-3. λΉλ μ€ν
./gradlew clean build -x test
# 3-4. λ컀 μ΄λ―Έμ§ μμ±
docker build -t λ컀μ΄λ―Έμ§λͺ
:λ²μ .
# 3-5. λ컀 컨ν
μ΄λ μ€ν
docker run -d \
--network host \
--name spring-container \
-e SPRING_DATASOURCE_URL=jdbc:mysql://λ΄λΆIP:3306/ncbt \
-e SPRING_DATASOURCE_USERNAME=μμ΄λ \
-e SPRING_DATASOURCE_PASSWORD=λΉλ°λ²νΈ \
-e SPRING_DATASOURCE_DRIVER_CLASS_NAME=com.mysql.cj.jdbc.Driver \
λ컀μ΄λ―Έμ§λͺ
:λ²μ
μ΄λ κ² νλλ κ²°κ΅β¦ !! CORS μλ¬κ° μ¬λΌμ§κ³ μ μμ μΌλ‘ ν΅μ μ΄ κ°λ₯ν΄μ‘λ€ !! κ³ μ λμ λ°°ν¬ μ±κ³΅ λ§λ§μΈλ€ ππ»
π€ λ°°μ΄μ
CORS λμ μ리
λ°°ν¬ νκ²½μμ μ κ²½μ¨μΌ ν μ μ΄ λ§€μ° λ§μλλ°, CORS λ μ λ§ λν΅ κ³ μνλ€.
λ‘컬μμ κ°λ°ν λλ κ·Έλ₯ 리μ‘νΈ ν¬νΈ localhost:3000 λ§ νμ©ν΄μ£Όλ©΄ λλκΉ λ¬Έμ κ° μμλλ°,
λ°°ν¬λ₯Ό νκ³ SSL μΈμ¦μλ₯Ό μ μ©ν΄λ³΄λ κ³ λ €ν΄μΌ ν μ μ΄ λ§μλ€.
preflight request
CORS μ simple request μ λ¬λ¦¬, λ¨Όμ OPTIONS λ©μλλ₯Ό ν΅ν΄ μ€μ μμ²μ μ μ‘νκΈ°μ μμ νμ§ νμΈνλ€. 200λ²λ μλ΅μ λ°μΌλ©΄ λ€μ μλμ μμ²μ 보λΈλ€.
μ POSTMAN μμλ CORS μ€λ₯κ° λ°μνμ§ μμκΉ ?
CORS μ μ± μλ° νλ¨μ βλΈλΌμ°μ β κ° μ€ννλ€. λ°λΌμ λΈλΌμ°μ μμ΄ μλ² κ° ν΅μ μ μ§ννλ€λ©΄ λΉμ°ν CORS μλ¬λ₯Ό νμΈν μ μλ κ²μ΄λ€.
Apache μλ²μ λν μ΄ν΄
μ μ΄μ Apache λ₯Ό μ€μΉν μ΄μ λ SSL μΈμ¦μκ° μΉ μλ²μμ λμνκΈ° λλ¬Έμ΄μλ€.
κ·Έλ λ€ λ³΄λ Apache μλ²λ λ¨μν SSL μ€μ μ μν κ²μ΄λΌκ³ μκ°μ΄ κ΅³μ΄μ§κ² λμλλ°,
μ€μμ Load Balancer μ μν λ κ²Ένλ€.
μΈλΆμμ https://api.ncbt.site λ‘ μμ²μ΄ λ€μ΄μ€λ κ²½μ° 443 ν¬νΈμμ λμνλ Apache κ° λ¨Όμ μμ²μ λ°λλ€.
κ·Έλ¦¬κ³ λ¦¬λ²μ€ νλ‘μλ‘ ν΄λΉ λλ©μΈμ λν μμ²μ μ€νλ§ μ ν리μΌμ΄μ
μΌλ‘ 보λ΄μ£Όλ κ²μ΄λ€.
λ§νμλ©΄ λλ¬Έ μν μΈ κ²μΈλ°, μ΄κ±Έ κΉμ΄ μκ°νμ§ λͺ»νκ³ νλλλ‘ μ€νλ§μμ CORS μ€μ μ νλ €κ³ νλ λ¬Έμ κ° μκΈ΄ κ²μ΄μλ€.
Apache μ μ€νλ§μ localhost λ‘ λ΄λΆμ μΈ ν΅μ μ νκ³ μμΌλ μλ‘ κ°μ CORS μ€μ μ νμκ° μλ€.
λ°λΌμ, λλ¬Έμ΄ λλ Apache μμλ§ CORS μ€μ μ ν΄μ£Όλ©΄ λλ κ²μ΄μλ€.
π μ°Έκ³ μλ£