🚀 Spring Boot에서 HTTPS 적용하는 방법
Spring Boot 애플리케이션을 HTTPS(SSL/TLS)로 실행하려면 SSL 인증서를 설정하고 HTTPS를 활성화해야 해.
주로 Self-Signed Certificate(개발용) 또는 Let's Encrypt/정식 인증서(운영용)를 사용해.
cetons 환경에서 springboot jar 파일로 업로드 하고 난 후 https ssl 적용하려고 했다.
다른 서버에서 서버로 cors 문제를 해결하기 위해서 nginx 와 ssl .p12 그리고
sudo semanage port -l | grep http_port_t
이 명령어로 허용가능한 포트를 확인 후 해당하는 포트로 톰캣 포트로 지정했다.
nginx 에서는 당연히 url 분기처리로 해당 로케이션에 맞는 부분에 따라 프록시 패스를 설정해주었다.
openssl pkcs12
-export -in /etc/letsencrypt/live/yourdomain.com/fullchain.pem
-inkey /etc/letsencrypt/live/yourdomain.com/privkey.pem
-out /etc/letsencrypt/live/yourdomain.com/fullchain.p12
-name tomcat
-CAfile /etc/letsencrypt/live/yourdomain.com/chain.pem
-caname root
이 코드는 pem -> p12로 변환 후 생성해주는 명령어이다.
우선 연습용 ssl 인증서를 스프링부트에서 사용하려면 pem -> pk12 형식으로 바꿔줘야 한다.
🔹 옵션 설명
- -alias mycert → 인증서의 별칭
- -keyalg RSA → 암호화 알고리즘
- -keystore keystore.p12 → 인증서 저장 파일
- -storetype PKCS12 → .p12 형식 사용
- -keysize 2048 → 키 크기(2048-bit)
- -validity 3650 → 인증서 유효 기간 (10년)
그리고
server.port= 허용 가능 포트번호들 중 하나
server.ssl.key-store-type=PKCS12
server.ssl.key-store=fullchain.p12
server.ssl.key-store-password=password
server.ssl.key-alias=tomcat
이 형식으로 다 설정을 해주었다.
🔹 설정 설명
- server.port=8443 → HTTPS는 보통 443 포트를 사용하지만, 로컬에서는 8443을 많이 씀
- server.ssl.key-store=classpath:keystore.p12 → .p12 인증서 위치 지정
- server.ssl.key-store-password=내가설정한비밀번호 → 인증서의 비밀번호
- server.ssl.key-store-type=PKCS12 → 인증서 형식
- server.ssl.key-alias=mycert → 생성한 인증서 별칭
🛠 HTTP 요청을 HTTPS로 강제 리다이렉트
일반적으로, http://localhost:8080 요청이 들어오면 자동으로 https://localhost:8443로 리다이렉트하도록 설정할 수 있어.
✅ 3️⃣ HttpToHttpsRedirectConfig 설정 추가
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
public class HttpToHttpsRedirectConfig {
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.requiresChannel(channel ->
channel.anyRequest().requiresSecure() // 모든 요청을 HTTPS로 강제
);
return http.build();
}
}
🔹 설명
- requiresChannel().anyRequest().requiresSecure() → 모든 HTTP 요청을 HTTPS로 리다이렉트
그리고 nginx 에 로케이션을 설정하고 난 후 스프링부트 서버에서
import org.springframework.context.annotation.Bean;
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 WebConfig {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("domain")
.allowedMethods("GET", "POST", "PUT", "DELETE", "HEAD")
.allowedHeaders("*")
.allowCredentials(true);
}
};
}
}
설정해주고 jar 로 배포한 후 테스트 했더니 !!!!
성공했다 !!!
그리고 이 스프링부트의 톰캣과 통신하려면
https://domain:port 으로 해줘야 한다.
🛠 운영 환경에서는 정식 인증서 사용하기
운영 환경에서는 Let's Encrypt, Cloudflare, DigiCert 같은 정식 SSL 인증서를 사용해야 해.
✅ 4️⃣ Let's Encrypt + Nginx 적용 (예제)
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
이렇게 하면 자동으로 SSL 인증서가 설치되면서, HTTP → HTTPS 리다이렉트도 자동으로 설정돼.
🎯 정리
단계작업 내용
1️⃣ | keytool로 Self-Signed 인증서 생성 (keystore.p12) |
2️⃣ | application.properties에서 HTTPS 설정 |
3️⃣ | HTTP → HTTPS 리다이렉트 적용 |
4️⃣ | 운영 환경에서는 정식 SSL 인증서 사용 (Let's Encrypt 등) |
이제 Spring Boot 애플리케이션을 HTTPS로 안전하게 실행할 수 있어! 🚀
별책부록
🎯 1. HTTPS + HTTP2 활성화 (성능 최적화)
기본적으로 HTTPS를 사용하면 HTTP/2를 함께 사용하면 속도와 효율성이 향상돼.
Spring Boot에서는 간단하게 server.http2.enabled=true 설정을 추가하면 돼.
✅ application.properties
server.port=8443
server.ssl.key-store=classpath:keystore.p12
server.ssl.key-store-password=내가설정한비밀번호
server.ssl.key-store-type=PKCS12
server.ssl.key-alias=mycert
server.http2.enabled=true
🚀 HTTP/2 장점
- 멀티플렉싱(Multiplexing) → 하나의 연결로 여러 요청 처리 가능
- 헤더 압축(Header Compression) → 네트워크 트래픽 감소
- 서버 푸시(Server Push) → 클라이언트가 요청하기 전에 리소스 미리 전송 가능
💡 주의: HTTP/2는 HTTPS 환경에서만 지원됨!
🎯 2. HSTS (HTTP Strict Transport Security) 적용
HSTS(Strict-Transport-Security)를 설정하면 브라우저가 강제로 HTTPS만 사용하도록 만들 수 있어.
이를 통해 MITM(중간자 공격)을 방지하고 보안성을 강화할 수 있어.
✅ Security 설정 추가 (SecurityConfig.java)
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
public class SecurityConfig {
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.headers(headers -> headers
.httpStrictTransportSecurity(hsts ->
hsts.includeSubDomains(true)
.maxAgeInSeconds(31536000) // 1년 (1년 동안 HTTPS만 사용하도록 브라우저에 지시)
)
);
return http.build();
}
}
💡 브라우저가 강제로 HTTPS를 사용하도록 만들어 HTTPS 연결 우회를 방지함.
🎯 3. Let's Encrypt 자동 갱신 (운영 환경)
운영 환경에서는 Let's Encrypt SSL 인증서를 사용하여 HTTPS를 적용하고, 이를 자동 갱신해야 해.
✅ Nginx + Let's Encrypt 설정 (예제)
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d example.com -d www.example.com
🔹 자동 갱신 설정
sudo crontab -e
0 3 * * * certbot renew --quiet
💡 매일 새벽 3시에 자동으로 SSL 인증서를 갱신함.
🎯 4. HTTPS + Mutual TLS (mTLS) 적용
기본 HTTPS는 서버 인증만 수행하지만, Mutual TLS(mTLS)를 적용하면 클라이언트도 인증서로 인증해야 해.
이를 통해 API 요청을 더욱 안전하게 만들 수 있어.
✅ application.properties
server.ssl.client-auth=need
server.ssl.trust-store=classpath:truststore.p12
server.ssl.trust-store-password=trustpassword
💡 client-auth=need → 클라이언트 인증서를 필수로 요구
✅ 클라이언트 인증서 발급 (client.p12)
keytool -genkey -alias client -keyalg RSA
-keystore client.p12 -storetype PKCS12 -keysize 2048 -validity 3650
이제 API 요청 시 서버와 클라이언트가 서로 인증서 검증을 진행해야 요청이 정상 처리됨! 🚀
🎯 5. HTTPS 로드밸런서 뒤에 Spring Boot 실행하기
운영 환경에서는 보통 로드밸런서(LB, Load Balancer) 뒤에서 HTTPS 트래픽을 받아서 처리해.
이 경우, Spring Boot 내부에서는 HTTP로 실행하되, X-Forwarded-Proto 헤더를 통해 HTTPS 요청을 감지해야 해.
✅ application.properties
server.forward-headers-strategy=native
💡 이 설정을 추가하면, Spring Boot가 로드밸런서에서 전달하는 X-Forwarded-Proto 헤더를 인식해서 올바른 URL을 유지할 수 있어.
🎯 6. HTTPS 트래픽을 HTTP로 다운그레이드 하기 (Reverse Proxy)
일부 서비스는 HTTPS 트래픽을 받아서 내부적으로 HTTP로 변환해야 할 때가 있어.
이 경우, Nginx Reverse Proxy를 이용해서 HTTPS를 HTTP로 변환할 수 있어.
✅ Nginx 설정 (HTTPS → HTTP 변환)
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
location / {
proxy_pass http://localhost:8080;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto https;
}
}
💡 외부에서는 HTTPS로 접속하지만, 내부에서는 HTTP로 통신하도록 설정
🎯 7. HTTPS + WebSocket (wss://) 설정
Spring Boot에서 HTTPS 환경에서 WebSocket을 사용하려면 wss:// 프로토콜을 사용해야 해.
기본적으로 WebSocket은 HTTP 프로토콜을 사용하기 때문에 HTTPS 환경에서는 wss://로 변경해야 해.
✅ WebSocket 설정 (WebSocketConfig.java)
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(new MyWebSocketHandler(), "/ws")
.setAllowedOrigins("https://example.com"); // HTTPS 환경에서만 허용
}
}
💡 외부에서는 wss://example.com/ws로 접속하도록 설정!
🔥 고급 HTTPS 기술 요약
기술설명
HTTP/2 활성화 | 성능 최적화 (멀티플렉싱, 서버 푸시) |
HSTS 적용 | 브라우저에서 HTTP 접속 차단, 강제 HTTPS |
Let's Encrypt 자동 갱신 | 인증서 갱신 자동화 (certbot renew) |
Mutual TLS (mTLS) | 클라이언트 인증서 검증 (보안 강화) |
로드밸런서 뒤 HTTPS 처리 | X-Forwarded-Proto 활용 |
Reverse Proxy로 HTTPS → HTTP 다운그레이드 | Nginx에서 내부 트래픽 변환 |
HTTPS + WebSocket (wss://) | 보안 WebSocket 지원 |
이제 Spring Boot 애플리케이션을 HTTPS로 강력하게 보호하고, 운영 환경에서 최적화할 수 있어! 🚀🔥
'Springboot' 카테고리의 다른 글
Springboot _ JWT (0) | 2025.02.08 |
---|---|
Springboot nginx wegsacket ssl 연결 통신 후 [WebSocket Error]java.net.ProtocolException: Expected HTTP 101 response but was '400 ' 에러해결법 (2) | 2024.10.14 |
vscode_ SpringBoot 프로젝트 만들기 (0) | 2024.08.20 |
Springboot -SSE ( 로컬에서는 실시간 o / https nginx 서버에서는 실시간 x) (0) | 2024.06.23 |
Springboot_ Redis SSE 작업 (0) | 2024.06.02 |