# 開發 Spring Boot project 時使用 Self-Signed Certificate 以支援 https [TOC] ###### tags: `spring` --- 在開發時常出現下列這些畫面: ![Google Chrome](https://i.imgur.com/hRzoAaY.png) (Google Chrome) ![Mozilla Firefox](https://i.imgur.com/xkz67LJ.png) ![Mozilla Firefox](https://i.imgur.com/NEMoV2q.png) (Mozilla Firefox) 由於開發 web application 時預設都是提供 http 服務,然而越來越多的 web services 要求專案僅能建置連線加密的環境,所以我們必須在開發期提供 https 服務。 ## 憑證格式 - **JKS**<sup>[![Wikipedia](https://en.wikipedia.org/static/favicon/wikipedia.ico =16x)](https://en.wikipedia.org/wiki/Java_KeyStore "Java KeyStore")[![IETF](https://docs.oracle.com/favicon.ico =16x)](https://docs.oracle.com/javase/6/docs/technotes/tools/solaris/keytool.html "keytool")</sup> 限用於 Java 環境的專有格式。 - **PKCS &#35;12**<sup>[![Wikipedia](https://en.wikipedia.org/static/favicon/wikipedia.ico =16x)](https://en.wikipedia.org/wiki/PKCS_12 "PKCS #12")[![IETF](https://tools.ietf.org/images/rfc.png =16x)](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 &#35;12 執行: ```shell $ keytool \ -importkeystore \ -srckeystore keystore.jks \ -destkeystore keystore.p12 \ -deststoretype pkcs12 ``` ### 直接生成 PKCS &#35;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 &#35;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 &#35;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)