unable to verify the first certificate
証明書チェーンが不完全です。
これは、接続しているWebサーバーが正しく構成されておらず、送信した証明書チェーンに中間証明書が含まれていないことを意味します。
証明書チェーン
次のようになります。
- サーバー証明書-中間者によって署名された証明書を保存します。
- 中間証明書-ルートによって署名された証明書を格納します。
- ルート証明書-自己署名証明書を保管します。
中間証明書は、サーバー証明書と共にサーバーにインストールする必要があります。
ルート証明書は、ソフトウェアアプリケーション、ブラウザ、オペレーティングシステムに組み込まれています。
証明書を提供するアプリケーションは完全なチェーンを送信する必要があります。これは、サーバー証明書自体とすべての中間物を意味します。ルート証明書はクライアントに知られているはずです。
問題を再現する
ブラウザを使用してhttps://incomplete-chain.badssl.comにアクセスします。
エラーは表示されません(アドレスバーの南京錠は緑色です)。
これは、サーバーから送信されない場合、ブラウザーがチェーンを完了する傾向があるためです。
次に、Nodeを使用してhttps://incomplete-chain.badssl.comに接続します。
// index.js
const axios = require('axios');
axios.get('https://incomplete-chain.badssl.com')
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
ログ:「エラー:最初の証明書を確認できません」。
解決
証明書チェーンを自分で完了する必要があります。
それを行うには:
1:不足している中間証明書を.pem
フォーマットで取得する必要があります。
A:使用してノードの内蔵証明書ストアを拡張しNODE_EXTRA_CA_CERTS
、
2b:または、ca
オプションを使用して独自の証明書バンドル(中間およびルート)を渡します。
1.中間証明書を取得するにはどうすればよいですか?
使用openssl
(Git for Windowsに付属)。
リモートサーバーの証明書の詳細を保存します。
openssl s_client -connect incomplete-chain.badssl.com:443 -servername incomplete-chain.badssl.com | tee logcertfile
私たちは発行者を探しています(中間証明書はサーバー証明書の発行者/署名者です):
openssl x509 -in logcertfile -noout -text | grep -i "issuer"
署名証明書のURIが表示されます。それをダウンロードしてください:
curl --output intermediate.crt http://cacerts.digicert.com/DigiCertSHA2SecureServerCA.crt
最後に、次のように変換し.pem
ます。
openssl x509 -inform DER -in intermediate.crt -out intermediate.pem -text
2a。NODE_EXTRA_CERTS
私はcross-envを使用してpackage.json
ファイルに環境変数を設定しています:
"start": "cross-env NODE_EXTRA_CA_CERTS=\"C:\\Users\\USERNAME\\Desktop\\ssl-connect\\intermediate.pem\" node index.js"
2b。ca
オプション
このオプションは、ノードの組み込みルートCAを上書きします。
そのため、独自のルートCAを作成する必要があります。ssl-root-casを使用します。
次に、https
証明書バンドル(ルートおよび中間)で構成されたカスタムエージェントを作成します。axios
リクエストを行うときにこのエージェントを渡します。
// index.js
const axios = require('axios');
const path = require('path');
const https = require('https');
const rootCas = require('ssl-root-cas').create();
rootCas.addFile(path.resolve(__dirname, 'intermediate.pem'));
const httpsAgent = new https.Agent({ca: rootCas});
axios.get('https://incomplete-chain.badssl.com', { httpsAgent })
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
カスタムhttps
エージェントを作成してに渡す代わりaxios
に、https
グローバルエージェントに証明書を配置できます。
// Applies to ALL requests (whether using https directly or the request module)
https.globalAgent.options.ca = rootCas;
リソース:
- https://levelup.gitconnected.com/how-to-resolve-certificate-errors-in-nodejs-app-involving-ssl-calls-781ce48daded
- https://www.npmjs.com/package/ssl-root-cas
- https://github.com/nodejs/node/issues/16336
- https://www.namecheap.com/support/knowledgebase/article.aspx/9605/69/how-to-check-ca-chain-installation
- /superuser/97201/how-to-save-a-remote-server-ssl-certificate-locally-as-a-file/
- .crtを.pemに変換する方法