首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

HTTPS 請求報錯 `Unrecognized SSL message, plaintext connection`:客戶端用 SSL 連接 HTTP 端口,確認服務端協議與端口匹配

     編輯:程式設計綜合問答

錯誤含義

`Unrecognized SSL message, plaintext connection` 直譯:**客戶端發起 SSL/TLS 握手 (ClientHello),但服務端返回的是明文 HTTP 響應**,而非 ServerHello。雙方協議不匹配:
客戶端:`https://host:port` (預期 TLS)
服務端:`https://host:port` (實際明文 HTTP)

典型誤配場景

客戶端配置服務端實際結果
`https://api.example.com:8080`HTTP 服務監聽 8080報此錯誤
`https://api.example.com:8443`HTTPS 服務監聽 8443正常
`https://api.example.com:8443`HTTPS 服務監聽 8443HTTP 客戶端收到 TLS 記錄 → `HTTP/1.1 400 Bad Request`

排查步驟

  1. 確認服務端真實監聽協議與端口:
    - 服務器上 `netstat -tlnp | grep :PORT` 查看進程。
    - `curl -v https://localhost:PORT` / `curl -vk https://localhost:PORT` 實測。
    - 檢查應用配置 (`application.yml`、`server.xml`、`nginx.conf`) 中 `port`、`ssl.enabled`、`scheme` 設置。
  2. 修正客戶端 URL 協議/端口:
    - 若服務端為 HTTP → 客戶端改 `https://...`。
    - 若服務端為 HTTPS → 客戶端用 `https://...` 並確保信任證書 (CA 或 `trustStore`)。
  3. 反向代理/網關層面:
    - Nginx `proxy_pass https://backend:8080;` (後端 HTTP) + 前端 `listen 443 ssl;` (前端 HTTPS) — **正確架構**。
    - 若 Nginx 直接 `proxy_pass https://backend:8443;` 但後端其實是 HTTP → 同報此錯。

代碼層面驗證

// Java HttpClient 4.x
HttpGet get = new HttpGet("https://host:port/path");
try (CloseableHttpClient client = HttpClients.custom()
        .setSSLContext(sslContext) // 若自簽證書需配置
        .build();
     CloseableHttpResponse resp = client.execute(get)) {
    System.out.println(EntityUtils.toString(resp.getEntity()));
} catch (javax.net.ssl.SSLException e) {
    if (e.getMessage().contains("Unrecognized SSL message")) {
        System.err.println("協議不匹配:請確認服務端是否真為 HTTPS,端口是否正確。");
    }
    throw e;
}

避坑口訣

  • 端口 ≠ 協議:80/8080/8000 常用 HTTP;443/8443/9443 常用 HTTPS,**但不絕對**,必須核對配置。
  • 開發環境常用 HTTP,生產環境 HTTPS:配置文件區分 profile,勿硬編碼協議。
  • 自簽證書需導入信任庫,否則會報 `PKIX path building failed`,而非本錯誤。

「curl -v 實測服務端協議,客戶端 URL 嚴格匹配」—— SSL 協議不匹配一查即中。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved