참고
https://opentutorials.org/course/228/4894
HTTPS vs HTTP
HTTP(Hypertext Transfer Protocol)은 Hypertext인 HTML을 전송하기 위한 통신 규약을 의미한다.
HTTP는 암호화되지 않은 방법으로 데이터를 전송하기 때문에 주고받는 메시지를 변조시키거나 가로채는 것이 쉽다. 따라서 보안성이 향상된 HTTP인 HTTPS가 탄생했다.
HTTPS의 S는 Over Secure Socket Layer의 약자로 보안이 강화된 HTTP를 말한다.
HTTPS와 SSL
HTTPS와 SSL은 동일한 의미로 쓰이기도 한다. 이는 인터넷과 웹의 관계와 비슷하다. 웹이 인터넷 위에서 돌아가듯이 HTTPS는 SSL 프로토콜 위에서 돌아가는 프로토콜이다.
HTTPS (SSL)을 사용하려면 keystore(인증서)를 만들어야한다
터미널에 다음과 같이 입력하면 keystore가 생성된다
$ keytool -genkey -alias spring -storetype PKCS12 -keyalg RSA -key$ keytool -genkey -alias spring -storetype PKCS12 -keyalg RSA -key
size 2048 -keystore keystor
e.p12 -validity 4000
Enter keystore password:
Re-enter new password:
What is your first and last name?
[Unknown]: DSUNNI
What is the name of your organizational unit?
[Unknown]: dsunni
What is the name of your organization?
[Unknown]: CEO
What is the name of your City or Locality?
[Unknown]: Seoul
What is the name of your State or Province?
[Unknown]: Seoul
What is the two-letter country code for this unit?
[Unknown]: WA
Is CN=DSUNNI, OU=dsunni, O=CEO, L=Seoul, ST=Seoul, C=WA correct?
[no]: yes
위와같이 keystore가 생성된 것을 확인할 수 있다.
server.ssl.key-store=keystore.p12
server.key-store-stype=PKCS12
server.ssl.key-store-password=123456
server.ssl.key-alias=spring
classpath:
를 추가해주면 된다.Spring Boot는 기본적으로 Tomcat이 사용하는 Connector를 하나만 등록해준다. 위와 같은 과정을 거치면 그 Connector에 SSL을 적용해준다.
따라서 앞으로 모든 요청은 앞에 https를 붙여야한다.
http로 localhost에 접속하면 위와 같은 Bad Request가 뜨는 걸 확인할 수 있다.
https로 들어가면 위와 같은 에러 화면이 뜬다.
브라우저가 서버에 요청을 보냈을 때 서버는 브라우저에게 인증서를 같이 보낸다. 그 때 브라우저가 인증서의 pubkey를 모르는 상태이면 위와 같은 에러 화면이 뜬다.
대부분의 공인인증서의 pubkey는 브라우저가 알고 있지만 Local에서 만든 keystore 안의 인증서는 브라우저가 알 수가 없다.
package me.dsunni;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@RestController
public class Application {
@GetMapping("/hello")
public String hello() {
return "Hello dsunni Spring Study :)";
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
https로 들어가면 200으로 data가 return 된는 것을 확인할 수 있다.
package me.dsunni;
import org.apache.catalina.connector.Connector;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@RestController
public class Application {
@GetMapping("/hello")
public String hello() {
return "Hello dsunni Spring Study :)";
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public ServletWebServerFactory serverFactory() {
TomcatServletWebServerFactory tomcatServletWebServerFactory
= new TomcatServletWebServerFactory();
tomcatServletWebServerFactory.addAdditionalTomcatConnectors(createStandardConnector());
return tomcatServletWebServerFactory;
}
private Connector createStandardConnector() {
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
connector.setPort(8080);
return connector;
}
}
새로운 Connector를 추가한 후 그 Connetor의 포트를 8080으로 설정해두면 http로 8080 포트 접속이 가능하다.
server.ssl.key-store=keystore.p12
server.key-store-stype=PKCS12
server.ssl.key-store-password=123456
server.ssl.key-alias=spring
server.port=8443
기존 톰캣 Connector의 포트를 8443으로 설정해두면 https로 8443 포트 접속이 가능하다.
http로 8080 접속이 가능하다
https로 8443 접속이 가능하다
참고
HTTP와 HTTP2
HTTP1은 기본적으로 Connection당 하나의 요청을 처리하기 때문에 동시 전송이 불가능하고 요청과 응답이 순차적으로 이루어진다.
이렇다 보니, HOL(Head Of Line) Blocking-특정응답지연, RTT(Round Trip TIme) 증가, 헤비한 Header구조라는 문제점들을 갖고잇다.
HTTP2는 HTTP1에 비해 성능뿐 아니라 속도 면에서도 월등하다.
- Multiplexed Streams : 한 커넥션에 여러개의 메세지를 동시에 주고 받을 수 있음
- Stream Prioritization : 요청 리소스간 의존관계를 설정
- Server Push : HTML문서상에 필요한 리소스를 클라이언트 요청없이 보내줄 수 있음
- Header Compression : Header 정보를 HPACK압충방식을 이용하여 압축전송
server.http2.enabled=true
위와 같이 추가하면 HTTP2 사용이 가능하다.
하지만 서버마다 제약사항이 다 다르다. undertow는 HTTPS만 적용되어있으면 어떠한 추가 설정이 없어도 HTTP2 사용이 가능하다.
반면 Tomcat은 매~우 복잡하다. (Tomcat 8 기준)
Tomcat 9, JDK 9는 추가적인 설치 없이 가능하다.
<properties>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.9</java.version>
<tomcat.version>9.0.10</tomcat.version>
</properties>
<properties>
를 추가해주면 java version과 tomcat version을 변경할 수 있다.
mvn package
를 하면 실행 가능한 JAR 파일이 하나 생성된다.
Spring Boot는 내장 jar라고 해서 jar안에 의존성인 모든 jar들을 묶어둔다. 그리고 이것들을 읽을 수 있는 파일(JarFile.class)이 함께 생성된다. 또한 Main Application을 실행하는 jar런처(JarLauncher.class)를 사용해 jar 파일을 실행한다.
spring-boot-maven-plugin이 패키징을 위와같이 해준다.
의존성 관리
spring-boot-starter-parent
, spring-boot-dependencies
이다.spring-boot-dependencies
: Spring Boot 주요 라이브러리들의 버전 관리@SpringBootApplication
안에는 다음이 들어있다.@EnableAutoConfiguration
@ComponentScan
@ConditionalOnMissingBean
: 기존에 그런 Bean이 없으면 자동설정으로 등록한다.Spring Boot의 주요 특징 중 하나는 Standalone Application(독립적으로 실행 가능한 애플리케이션)을 만들어 준다는 것이다.
그렇기 때문에 내장 웹서버에 대한 기능이 잔뜩 들어가있는 것이다.