SpringBoot服務(wù)間使用自簽名證書實現(xiàn)https雙向認證

以服務(wù)server-one和server-two之間使用RestTemplate以https調(diào)用為例

一雷激、生成密鑰

需要生成server-one和server-two的客戶端密鑰和一個信任庫密鑰

1理郑、生成TrustStore(信任庫)

keytool -genkey -alias trustkeys -storetype PKCS12 -keyalg RSA -keysize 2048 -keystore trustKeys.p12 -validity 36500
image-20210521153617347.png

2、生成server-one客戶端密鑰

keytool -genkey -alias server-one -storetype PKCS12 -keyalg RSA -keysize 2048 -keystore server-one.p12 -validity 36500
image-20210521153826177.png

3寂殉、生成server-two客戶端密鑰

keytool -genkey -alias server-two -storetype PKCS12 -keyalg RSA -keysize 2048 -keystore server-two.p12 -validity 36500
image-20210521153946789.png
  • genkey 表示要創(chuàng)建一個新的密鑰囚巴。
  • alias 表示 keystore 的別名。
  • keyalg 表示使用的加密算法是 RSA 友扰,一種非對稱加密算法彤叉。
  • keysize 表示密鑰的長度。
  • keystore 表示生成的密鑰存放位置村怪。
  • validity 表示密鑰的有效時間秽浇,單位為天。

二甚负、導(dǎo)出客戶端公鑰添加到信任庫

1柬焕、導(dǎo)出server-one的公鑰

keytool -keystore server-one.p12 -export -alias server-two -file server-one-publicKey.cer
image-20210521154602190.png

2审残、導(dǎo)出server-two的公鑰

keytool -keystore server-two.p12 -export -alias server-two -file server-two-publicKey.cer
image-20210521154637261.png

3、添加客戶端公鑰到信任庫

keytool -import -alias server-one -v -file server-one-publicKey.cer -keystore trustKeys.p12

keytool -import -alias server-two -v -file server-two-publicKey.cer -keystore trustKeys.p12
image-20210521154826052.png

三斑举、配置SpringBoot支持https

1搅轿、拷貝相應(yīng)密鑰到resources

service-one

image-20210521155045950.png

service-two

image-20210521155132357.png

2、修改application.yml配置文件

service-one

server:
  ssl:
    enable: true
    client-auth: need #雙向認證need
    key-store: classpath:ssl/server-one.p12
    key-store-password: 123456
    key-store-type: PKCS12
    key-alias: server-one
    trust-store: classpath:ssl/trustKeys.p12
    trust-store-password: 123456
    trust-store-type: PKCS12

service-two

server:
  ssl:
    enable: true
    client-auth: need #雙向認證need
    key-store: classpath:ssl/server-two.p12
    key-store-password: 123456
    key-store-type: PKCS12
    key-alias: server-two
    trust-store: classpath:ssl/trustKeys.p12
    trust-store-password: 123456
    trust-store-type: PKCS12

3富玷、啟動服務(wù)并驗證https

瀏覽器訪問:https://localhost:8081/server-one/get

image-20210521161739758.png

此時無法訪問

單擊server-one.p12或server-two.p12為瀏覽器安裝證書

安裝后再次訪問
image-20210521162019112.png

點擊確定后即可訪問到頁面

4璧坟、配置RestTemplate

pom添加httpclient支持

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.13</version>
</dependency>

設(shè)置RestTemplate支持https請求

package com.example.serviceone.config;

import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.util.ResourceUtils;
import org.springframework.web.client.RestTemplate;

import javax.net.ssl.*;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.*;
import java.security.cert.CertificateException;
import java.time.Duration;

/**
 * Created by chenzan on 2021/05/21
 */
@Configuration
public class RestTemplateConfig {
    @Value("${server.ssl.key-store}")
    String clientPath;
    @Value("${server.ssl.key-store-password}")
    String clientPass;
    @Value("${server.ssl.key-store-type}")
    String clientKeyType;
    @Value("${server.ssl.trust-store}")
    String trustPath;
    @Value("${server.ssl.trust-store-password}")
    String trustPass;
    @Value("${server.ssl.trust-store-type}")
    String trustKeyType;

    @Bean
    public RestTemplate restTemplate() {
        RestTemplate restTemplate = null;
        try {
            HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
            // 客戶端證書類型
            KeyStore clientStore = KeyStore.getInstance(clientKeyType);
            // 加載客戶端證書,即自己的私鑰
            clientStore.load(new FileInputStream(ResourceUtils.getFile(clientPath)), clientPass.toCharArray());
            // 創(chuàng)建密鑰管理工廠實例
            KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
            // 初始化客戶端密鑰庫
            keyManagerFactory.init(clientStore, clientPass.toCharArray());
            KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();

            // 創(chuàng)建信任庫管理工廠實例
            TrustManagerFactory trustManagerFactory = TrustManagerFactory
                    .getInstance(TrustManagerFactory.getDefaultAlgorithm());
            KeyStore trustStore = KeyStore.getInstance(trustKeyType);
            trustStore.load(new FileInputStream(ResourceUtils.getFile(trustPath)), trustPass.toCharArray());

            // 初始化信任庫
            trustManagerFactory.init(trustStore);
            TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
            // 建立TLS連接
            SSLContext sslContext = SSLContext.getInstance("TLS");
            // 初始化SSLContext
            sslContext.init(keyManagers, trustManagers, new SecureRandom());
            // INSTANCE 忽略域名檢查
            SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
            CloseableHttpClient httpclient = HttpClients
                    .custom()
                    .setSSLSocketFactory(sslConnectionSocketFactory)
                    .setSSLHostnameVerifier(new NoopHostnameVerifier())
                    .build();
            requestFactory.setHttpClient(httpclient);
            requestFactory.setConnectTimeout((int) Duration.ofSeconds(15).toMillis());
            restTemplate = new RestTemplate(requestFactory);
        } catch (KeyManagementException | FileNotFoundException | NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyStoreException | CertificateException | UnrecoverableKeyException | IOException e) {
            e.printStackTrace();
        }
        return restTemplate;
    }
}

添加測試代碼

server-one和server-two分別在Controller添加代碼

server-two中

@RestController
public class ServerTwoController {

    @RequestMapping("/get")
    public String get() {
        return "two";
    }
}

server-one中

@RestController
public class ServerOneController {

    @RequestMapping("/get")
    public String get() {
        return "one";
    }
}

添加test代碼

@SpringBootTest
public class ServiceOneApplicationTests {
    String url = "https://localhost:8081/server-two/get";
    @Autowired
    private RestTemplate restTemplate;

    @Test
    public void testHttpsGet() {
        ResponseEntity<String> forEntity = restTemplate.getForEntity(url, String.class);
        System.out.println(forEntity.toString());
    }
}

執(zhí)行返回

<200,two,[Content-Type:"text/plain;charset=UTF-8", Content-Length:"3", Date:"Fri, 21 May 2021 08:12:51 GMT", Keep-Alive:"timeout=60", Connection:"keep-alive"]>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末赎懦,一起剝皮案震驚了整個濱河市雀鹃,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌励两,老刑警劉巖褐澎,帶你破解...
    沈念sama閱讀 218,525評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異伐蒋,居然都是意外死亡工三,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評論 3 395
  • 文/潘曉璐 我一進店門先鱼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來俭正,“玉大人,你說我怎么就攤上這事焙畔〉Ф粒” “怎么了?”我有些...
    開封第一講書人閱讀 164,862評論 0 354
  • 文/不壞的土叔 我叫張陵宏多,是天一觀的道長儿惫。 經(jīng)常有香客問我,道長伸但,這世上最難降的妖魔是什么肾请? 我笑而不...
    開封第一講書人閱讀 58,728評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮更胖,結(jié)果婚禮上铛铁,老公的妹妹穿的比我還像新娘。我一直安慰自己却妨,他們只是感情好饵逐,可當(dāng)我...
    茶點故事閱讀 67,743評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著彪标,像睡著了一般倍权。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上捞烟,一...
    開封第一講書人閱讀 51,590評論 1 305
  • 那天薄声,我揣著相機與錄音萌业,去河邊找鬼。 笑死奸柬,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的婴程。 我是一名探鬼主播廓奕,決...
    沈念sama閱讀 40,330評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼档叔!你這毒婦竟也來了桌粉?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,244評論 0 276
  • 序言:老撾萬榮一對情侶失蹤衙四,失蹤者是張志新(化名)和其女友劉穎铃肯,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體传蹈,經(jīng)...
    沈念sama閱讀 45,693評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡押逼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,885評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了惦界。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片挑格。...
    茶點故事閱讀 40,001評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖沾歪,靈堂內(nèi)的尸體忽然破棺而出漂彤,到底是詐尸還是另有隱情,我是刑警寧澤灾搏,帶...
    沈念sama閱讀 35,723評論 5 346
  • 正文 年R本政府宣布挫望,位于F島的核電站,受9級特大地震影響狂窑,放射性物質(zhì)發(fā)生泄漏媳板。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,343評論 3 330
  • 文/蒙蒙 一泉哈、第九天 我趴在偏房一處隱蔽的房頂上張望拷肌。 院中可真熱鬧,春花似錦旨巷、人聲如沸巨缘。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽若锁。三九已至,卻和暖如春斧吐,著一層夾襖步出監(jiān)牢的瞬間又固,已是汗流浹背仲器。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留仰冠,地道東北人乏冀。 一個月前我還...
    沈念sama閱讀 48,191評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像洋只,于是被迫代替她去往敵國和親辆沦。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,955評論 2 355

推薦閱讀更多精彩內(nèi)容