테스트환경에서 SSL/HTTPS 설정하기

2025. 1. 15. 17:56TIL

 

Server

현재 로그인을 할때 AccessToken은 헤더에 담아서 클라이언트에게 보내고 RefreshToken은 secure=ture 설정을 해주었기때문에 쿠키가 HTTPS 연결에서만 전달이 되는 상황이다.

@PostMapping("/login")
fun login(@RequestBody request: LoginRequest, response: HttpServletResponse): ResponseEntity<
        Map<String, String>> {

    val tokenResponse = oAuthService.login(request)

    // ACCESS TOKEN을 헤더에 담아서 반환
    val headers = HttpHeaders()
    headers.add("Authorization", "Bearer ${tokenResponse.accessToken}")

    // REFRESH TOKEN을 쿠키에 저장
    val refreshTokenCookie = Cookie("refreshToken", tokenResponse.refreshToken).apply {
        isHttpOnly = true
        secure = true
        path = "/"
    }
    response.addCookie(refreshTokenCookie)

    val messageJson = mapOf(
        "message" to "토큰 발급 성공"
    )

    return ResponseEntity.ok()
        .headers(headers)
        .body(messageJson)
}

 

지금 테스트 단계에서는 HTTP를 이용하고 있기 때문에 secure = true 부분을 삭제해도 되지만 어차피 추후에 배포를 할때 HTTPS로 배포를 할것이기 때문에 SSL/HTTPS를 적용을 할것이다.

 

자체 성명 (Self-Signed) 인증서 생성

keytool -genkeypair -alias my-ssl-key -keyalg RSA -keysize 2048 -storetype PKCS12 -keystore keystore.p12 -validity 3650

 

 

생성된 keystore 파일은 main/resources 하위에 위치하고 gitingore에 명시하여 git에 공유하지 않도록 설정한다.

 

application.yml

server:
  port: 443
  ssl:
    enabled: true
    key-store: classpath:keystore.p12
    key-store-type: PKCS12
    key-alias: my-ssl-key
    key-store-password: ******

 

포트번호 443으로 접속하면 https 연결이 된것을 확인할 수 있다.

https://localhost/swagger-ui/index.html#/

주의 요함이라고 표시가 된 이유는 인증기관(CA)에서 인증받은 인증서가 아닌 자체 서명 인증서이기 때문에 경고 표시가 나오는것이다. 나중에 실서비스를 할때는 CA에서 인증받은 인증서를 사용하거나 AWS에서 관리하는 SSL 인증서를 사용할 예정이다.

 

Client

서버 뿐만 아니라 클라이언트에서도 https 연결이 되어야하기 때문에 클라이언트도 마찬가지로 임시로 자체 성명을 이용한다.

클라이언트 ssl 생성

https://slproweb.com/products/Win32OpenSSL.html

 

Win32/Win64 OpenSSL Installer for Windows - Shining Light Productions

Minimum system requirements: Windows XP or later 32MB RAM 200MHz CPU 30MB hard drive space Recommended system requirements: Windows XP or later 128MB RAM 500MHz CPU 300MB hard drive space October 22, 2024 - OpenSSL 3.4 is available. Users should currently

slproweb.com

Win64 OpenSSL v3.4.0  exe 파일 설치 및 실행 

(light버전으로 설치하면 openssl.cfg 파일이 생성되지 않기때문에 light버전을 설치하면 안된다!!)

 

환경변수 설정

 

openssl version

제대로 설정되었는지 확인

 

cert 파일 생성

mkdir cert

 

private key 설정

openssl genrsa -out client-key.pem 2048

 

CSR 설정

openssl req -new -key client-key.pem -out client-csr.pem

 

인증서 발급

openssl x509 -req -in client-csr.pem -signkey client-key.pem -out client-cert.pem -days 365

 

cert 폴더 내 파일이 생성된것을 확인

서버 인증서 발급

openssl req -nodes -new -x509 -keyout server-key.pem -out server-cert.pem -days 365

 

기존 server.js

더보기
// server.js
const express = require('express');
const path = require('path');

const app = express();
const port = 3000;

app.use(express.static(path.join(__dirname, 'public')));

app.get('/', (req, res) => {
    res.sendFile(path.join(__dirname, 'public', 'index.html'));
});

app.listen(port, () => {
    console.log(`Frontend server is running on http://localhost:${port}`);
});

 

HTTPS 적용된 server.js

더보기
// server.js
const express = require('express');
const path = require('path');
const fs = require('fs');
const https = require('https');
const http = require('http');

const app = express();
const httpsPort = 3000;
const httpPort = 3001; // HTTP 포트 (리디렉션용)

// SSL 인증서 경로 (key.pem, cert.pem)
const sslOptions = {
    key: fs.readFileSync(path.join(__dirname, 'cert', 'server-key.pem')),
    cert: fs.readFileSync(path.join(__dirname, 'cert', 'server-cert.pem'))
};

// 정적 파일 제공
app.use(express.static(path.join(__dirname, 'public')));

// 라우트 설정
app.get('/', (req, res) => {
    res.sendFile(path.join(__dirname, 'public', 'index.html'));
});

// HTTPS 서버 실행
https.createServer(sslOptions, app).listen(httpsPort, () => {
    console.log(`Frontend server is running on https://localhost:${httpsPort}`);
});

// HTTP 요청을 HTTPS로 리디렉션
http.createServer((req, res) => {
    res.writeHead(301, { "Location": `https://localhost:${httpsPort}${req.url}` });
    res.end();
}).listen(httpPort, () => {
    console.log(`HTTP server is running on http://localhost:${httpPort} (Redirecting to HTTPS)`);
});

 

node server.js

HTTPS로 연결이 된것을 확인할 수 있다.

 

클라이언트 접속

https://localhost:3000

 

클라이언트도 https로 접속이 잘 된것을 확인할 수 있다.