在前后端分離的項目中,如果需要通過訪問服務器,直接請求會引起跨域問題,這時我們需要使用 webpack 開發服務器中的代理來把特定的 URL 轉發到后端服務器。
在代理 https 協議的地址時,又會因為 https 證書問題導致接口訪問失敗,報錯 500!
先說解決方法:代理配置和 http 協議無其他差別,降低 node 版本到 11 以下,就能解決這個問題。
一、發現問題
我想要訪問接口 https://172.16.255.241:4000/api/robot/suggest?query=q&use_rc=1&use_faq=1&use_mapping=1
, 於是我在項目中采取如下步驟(參考:代理到后端服務器)
- 在項目的 src/ 目錄下創建一個 proxy.conf.json 文件
- 往這個代理配置文件中添加如下內容:
"/api": {
"target": "https://172.16.255.241:4000",
"secure": false,
"changeOrigin": true,
"logLevel": "debug"
}
- 在 CLI 配置文件 angular.json 中為 serve 目標添加 proxyConfig 選項:
...
"architect": {
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "your-application-name:build",
"proxyConfig": "src/proxy.conf.json"
},
...
4. 在 package.json 啟動腳本中配置
...
"scripts": {
"ng": "ng",
"start": "ng --proxy-config proxy.conf.json",
},
...
- 使用
npm start
啟動項目,調用接口時,報錯 500
二、找到原因
當我發現這個問題后,運維同學說可能是 https 證書問題,於是他把 http 換成了 http 協議。我改了 proxy.conf.json 文件中代理配置 target,把 https 改為了 http ,於是請求正常,200。
網上去找解決方法,大家的解決方法都是我之前寫的那樣。於是讓旁邊同學看看,他新建了一個 ng 項目,和我同樣的配置,發現能購正常訪問。於是我也新建了一個項目,同樣的配置,還是報錯 500。
那就不是項目本身配置不對了,而是電腦配置或者其他 node、webpack 等配置不同導致。他用的 node v10.16.0,而我用的是 node v13.12.0。
三、解決問題
於是我切換 node 版本到 v10.16.0 就解決了500 錯誤的問題。(參考 mac 下的 node 管理工具:使用 nvm 管理不同版本的 node 與 npm)
在 如何修復升級 node 版本后的 eproto 錯誤 中解釋道:
在 node.js 10 最小支持 TLS 版本是 TLSv1.0,但自從 v11.4.0, 是提高到 TLSv1.2。我懷疑 cidadao.sinesp.gov.br 的證書是用 TLSv1.0 簽署的,它可以在 Node.js v10.15.3 上使用,但不能在 v12.2.0 上使用。
並且給出解決方法:
要使 Node.js 接受 TLSv1.0,可以使用 --ls-min-v1.0 選項來啟動 Node.js 進程。
於是將 package.json 啟動腳本中配置 start
...
"scripts": {
"ng": "ng",
"start": "node --tls-min-v1.0 node_modules/@angular/cli/bin/ng serve -o --proxy-config proxy.conf.json",
},
...
在換回 node v13.12.0 版本, 接口又可以正常訪問了。
四、總結
當希望使用 https 協議地址代理到后端服務器時,你可以像使用 http 協議的地址一樣配置好項目。然后使用以下任意一種方法解決非安全的 ssl 連接並且傳輸數據(https 證書不受信)。
- 降低 node.js 版本,如使用 node v10.16.0。
- 在 package.json 啟動腳本中配置 start 為
node --tls-min-v1.0 node_modules/@angular/cli/bin/ng serve -o --proxy-config proxy.conf.json
另外,webpack 代理支持中國呢明確指出(參考:secure 配置)
默認情況下,使用無效證書運行在HTTPS上的后端服務器將不被接受。
在使用 https 協議時,secure 設置為 false。