인프런에서 백기선님의 스프링 부트 개념과 활용을 수강하고 개인적으로 공부한 내용을 정리한 글입니다.

HTTPS 적용하기

HTTP는 평문으로 통신을 하기 때문에 보안상의 문제가 있다. HTTPS는 HTTP 통신에 암호화를 적용해 보안이 강화된 프로토콜이다.

  1. keystore는 암호화/복호화와 디지털 서명에 필요한 key, certificate를 추상화해서 제공하는 Java의 인터페이스다. keytool은 keystore 기반으로 인증서와 key를 관리할 수 있는 유틸리티로 JDK에 포함되어 있다. keytool -genkey 명령어로 keystore를 만들어보자.

     keytool -genkey -alias tomcat -storetype PKCS12 -keyalg RSA -keysize 2048 -keystore keystore.p12 -validity 4000
    어차피 로컬에서만 사용할 인증서라 이름과 비밀번호 외엔 지정하지 않았다.
  1. application.properties에 다음과 같이 key-value를 추가한다. SSL은 server.ssl.*로 시작하는 properties로 설정이 가능하다.

    server.ssl.key-store= keystore.p12
    server.ssl.key-store-password={본인이 설정한 비밀번호}
    server.ssl.keyStoreType= PKCS12
    server.ssl.keyAlias= tomcat

    이렇게 하면 tomcat이 사용하는 디폴트 커넥터에 SSL이 적용된다. 앞으로 모든 request엔 https를 붙여야 한다.

http://localhost:8080으로 접속하면 Bad request 에러가 발생한다. 8080번 포트는 더이상 http 요청을 받지 않도록 설정했기 때문이다.

https://localhost:8080으로 접속하면 연결이 비공개로 설정되어 있지 않다는 경고(err_cert_authority_invalid)가 나타난다.

요청을 보낸 순간 서버는 클라이언트(브라우저)에게 인증서를 전달해주며, 브라우저는 서버로부터 전달받은 인증서를 루트 인증서 저장소(cacerts)에 있는 루트 인증서로 신뢰성 검증을 하게 된다. 방금 로컬에서 만든 인증서는 공식적으로 발급된 인증서가 아니다.

 

브라우저가 인증서의 public key를 모르는 상태이기 때문에 신뢰성 검증을 할 수 없어 이대로 연결해도 괜찮느냐 묻는 경고 화면이 나타났다. 이 경고를 해결하고 싶다면 클라이언트의 루트 인증서 저장소에 서버에 인증서를 발급한 인증기관의 루트인증서를 등록해야 한다. (지금은 공부하는 목적으로 만드는거니 굳이 여기까진 하지 않는다.)

멀티 커넥터 설정하기

https를 적용하고 나면 http를 받을수 있는 커넥터가 없다. 만약 http를 사용하고 싶다면 코딩으로 멀티 커넥터 설정을 해야 한다. (멀티 커넥터 구현 예제, 공식 문서 예제)

@SpringBootApplication
@RestController
public class Application {

    @GetMapping("/hello")
    public String hello() {
        return "<h1>Hello</h1>";
    }

    @Bean
    public ServletWebServerFactory servletContainer() {
        TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
        tomcat.addAdditionalTomcatConnectors(createStandardConnector());
        return tomcat;
    }

    private Connector createStandardConnector() {
        Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
        connector.setPort(8080);
        return connector;
    }

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

8080은 http를, 8443은 https로 요청을 받을 수 있게 포트 번호를 8443으로 설정하자.

server.ssl.key-store= keystore.p12
server.ssl.key-store-password={본인이 설정한 비밀번호}
server.ssl.keyStoreType= PKCS12
server.ssl.keyAlias= tomcat
server.port=8443

HTTP2 활성화하기

http2는 http 1.1을 개선한 것으로, 아래와 같은 것들을 이용해 http 1.1보다 응답~요청 성능이 우수하다.

http2를 사용하도록 요청을 보내도 응답 결과를 보면 http1.1을 사용하고 있다.

HTTP2를 사용하려면 기본적으로 SSL 적용이 선행되어야 한다. https가 적용되어 있다면 application.properties에 다음 한 줄을 추가한다.

server.http2.enabled=true

Java 9, tomcat 9 이상의 버전을 사용하지 않으면 설정이 매우 귀찮아진다. (참고)

pom.xml에서 Java와 tomcat의 버전을 올리자.

    <properties>
        <java.version>1.9</java.version>
        <tomcat.version>9.0.37</tomcat.version>
    </properties>

다시 한 번 동일하게 요청을 보내보면 http2를 사용하고 있다.

References