# 開發 Spring Boot project 時使用 Self-Signed Certificate 以支援 https
[TOC]
###### tags: `spring`
---
在開發時常出現下列這些畫面:

(Google Chrome)


(Mozilla Firefox)
由於開發 web application 時預設都是提供 http 服務,然而越來越多的 web services 要求專案僅能建置連線加密的環境,所以我們必須在開發期提供 https 服務。
## 憑證格式
- **JKS**<sup>[](https://en.wikipedia.org/wiki/Java_KeyStore "Java KeyStore")[](https://docs.oracle.com/javase/6/docs/technotes/tools/solaris/keytool.html "keytool")</sup>
限用於 Java 環境的專有格式。
- **PKCS #12**<sup>[](https://en.wikipedia.org/wiki/PKCS_12 "PKCS #12")[](https://tools.ietf.org/html/rfc7292 "Request for Comments: 7292")</sup>: Personal Information Exchange Syntax v1.1
業界普遍使用的格式。
### 生成 JKS
執行:
```shell
$ keytool \
-genkeypair \
-alias localhost \
-keyalg RSA \
-keysize 2048 \
-keystore keystore.jks \
-validity 3650
```
#### 將 JKS 轉為 PKCS #12
執行:
```shell
$ keytool \
-importkeystore \
-srckeystore keystore.jks \
-destkeystore keystore.p12 \
-deststoretype pkcs12
```
### 直接生成 PKCS #12
執行:
```shell
$ keytool \
-genkeypair \
-alias localhost \
-keyalg RSA \
-keysize 2048 \
-storetype PKCS12 \
-keystore keystore.p12 \
-validity 3650
```
接下來回答一些問題:
```
Enter keystore password:
```
輸入至少6個字元的密碼。
```
Re-enter new password:
```
再輸入密碼一次。
```
What is your first and last name?
[Unknown]:
```
輸入名字或直接按`Enter`鍵。
```
What is the name of your organizational unit?
[Unknown]:
```
輸入部門名稱或直接按`Enter`鍵。
```
What is the name of your organization?
[Unknown]:
```
輸入組織名稱或直接按`Enter`鍵。
```
What is the name of your City or Locality?
[Unknown]:
```
輸入地區或直接按`Enter`鍵。
```
What is the name of your State or Province?
[Unknown]:
```
輸入州、省或直接按`Enter`鍵。
```
What is the two-letter country code for this unit?
[Unknown]:
```
輸入國家或直接按`Enter`鍵。
```
Is CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown correct?
[no]:
```
輸入`yes`確認以上資訊無誤;當出現:
```
Generating 2,048 bit RSA key pair and self-signed certificate (SHA256withRSA) with a validity of 3,650 days
for: CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown
```
時表示已生成 PKCS #12 keystore。
## 整合到 Spring Boot 專案
先將前面生成的 keystore 檔移或複製到 project 裡:
```
src/main/resources/keystore.(jks|p12)
```
### Server 端專案
編輯`src/main/resources/application.properties`:
```properties
# 憑證別名
server.ssl.key-alias=localhost
# 僅提供 https 服務(不使用 http)
server.ssl.enabled=true
# 憑證路徑
server.ssl.key-store=classpath:keystore.(jks|p12)
# 憑證密碼
server.ssl.key-store-password=password
# 憑證格式:JKS 或 PKCS12
server.ssl.key-store-type=PKCS12
```
### Client 端專案
編輯`src/main/resources/application.properties`:
```properties
# 憑證路徑
trust.store=classpath:keystore.p12
# 憑證密碼
trust.store.password=password
```
忘了下面這段代碼是在幹嘛的…
```java
RestTemplate restTemplate() throws Exception {
SSLContext sslContext = new SSLContextBuilder().
loadTrustMaterial(
trustStore.getURL(),
trustStorePassword.toCharArray()
).
build();
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext);
HttpClient httpClient = HttpClients.custom().
setSSLSocketFactory(socketFactory).
build();
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient);
return new RestTemplate(factory);
}
```
## 心得
1. 考量到相容性建議還是以 **PKCS #12** 為優先。
2. 建立獨立的`application(-ENVIRONMENT).properties`給不同執行環境使用。
## SpringBoot - Error parsing HTTP request header (Oauth2 https endpoints)
```
java.io.IOException: Unable to unwrap data, invalid status [CLOSED]
```
> To work Oauth2 endpoints in local you have install certs in local JRE truststore.
> Use below command to add that in local trust store:
```
$ keytool -keystore cacerts -import -trustcacerts -file "file path to cert"
```
> To make it work in postman: In chrome browser, install localhost cert to “Trusted Root Certification Authorities”
[出處](https://stackoverflow.com/questions/51501360/springboot-error-parsing-http-request-header-oauth2-https-endpoints)