本文摘錄自《Nodejs學習筆記》,更多章節及更新,請訪問 github主頁地址。歡迎加羣交流,羣號 197339705。node
這個模塊的重要性,基本不用強調了。在網絡安全問題日益嚴峻的今天,網站採用HTTPS是個必然的趨勢。git
在nodejs中,提供了 https 這個模塊來完成 HTTPS 相關功能。從官方文檔來看,跟 http 模塊用法很是類似。github
本文主要包含兩部分:web
經過客戶端、服務端的例子,對https模塊進行入門講解。算法
如何訪問安全證書不受信任的網站。(以 12306 爲例子)chrome
篇幅所限,本文沒法對 HTTPS協議 及 相關技術體系 作過多講解,有問題歡迎留言交流。瀏覽器
跟http模塊的用法很是像,只不過請求的地址是https協議的而已,代碼以下:安全
var https = require('https'); https.get('https://www.baidu.com', function(res){ console.log('status code: ' + res.statusCode); console.log('headers: ' + res.headers); res.on('data', function(data){ process.stdout.write(data); }); }).on('error', function(err){ console.error(err); });
對外提供HTTPS服務,須要有HTTPS證書。若是你已經有了HTTPS證書,那麼能夠跳過證書生成的環節。若是沒有,能夠參考以下步驟bash
mkdir cert cd cert
openssl genrsa -out chyingp-key.pem 2048
openssl req -new \ -sha256 -key chyingp-key.key.pem \ -out chyingp-csr.pem \ -subj "/C=CN/ST=Guandong/L=Shenzhen/O=YH Inc/CN=www.chyingp.com"
openssl x509 \ -req -in chyingp-csr.pem \ -signkey chyingp-key.pem \ -out chyingp-cert.pem
代碼以下:服務器
var https = require('https'); var fs = require('fs'); var options = { key: fs.readFileSync('./cert/chyingp-key.pem'), // 私鑰 cert: fs.readFileSync('./cert/chyingp-cert.pem') // 證書 }; var server = https.createServer(options, function(req, res){ res.end('這是來自HTTPS服務器的返回'); }); server.listen(3000);
因爲我並無 www.chyingp.com 這個域名,因而先配置本地host
127.0.0.1 www.chyingp.com
啓動服務,並在瀏覽器裏訪問 http://www.chyingp.com:3000。注意,瀏覽器會提示你證書不可靠,點擊 信任並繼續訪問 就好了。
這裏以咱們最喜好的12306最爲例子。當咱們經過瀏覽器,訪問12306的購票頁面 https://kyfw.12306.cn/otn/reg... 時,chrome會阻止咱們訪問,這是由於,12306的證書是本身頒發的,chrome沒法確認他的安全性。
對這種狀況,能夠有以下處理方式:
中止訪問:着急搶票回家過年的老鄉表示沒法接受。
無視安全警告,繼續訪問:大部分狀況下,瀏覽器是會放行的,不過安全提示還在。
導入12306的CA根證書:瀏覽器乖乖就範,認爲訪問是安全的。(實際上仍是有安全提示,由於12306用的簽名算法安全級別不夠)
一樣的,經過 node https client 發起請求,也會遇到一樣問題。咱們作下實驗,代碼以下:
var https = require('https'); https.get('https://kyfw.12306.cn/otn/regist/init', function(res){ res.on('data', function(data){ process.stdout.write(data); }); }).on('error', function(err){ console.error(err); });
運行上面代碼,獲得下面的錯誤提示,意思是 安全證書不可靠,拒絕繼續訪問。
{ Error: self signed certificate in certificate chain at Error (native) at TLSSocket.<anonymous> (_tls_wrap.js:1055:38) at emitNone (events.js:86:13) at TLSSocket.emit (events.js:185:7) at TLSSocket._finishInit (_tls_wrap.js:580:8) at TLSWrap.ssl.onhandshakedone (_tls_wrap.js:412:38) code: 'SELF_SIGNED_CERT_IN_CHAIN' }
ps:我的認爲這裏的錯誤提示有點誤導人,12306網站的證書並非自簽名的,只是對證書籤名的CA是12306自家的,不在可信列表裏而已。自簽名證書,跟本身CA簽名的證書仍是不同的。
相似在瀏覽器裏訪問,咱們能夠採起以下處理:
不建議:忽略安全警告,繼續訪問;
建議:將12306的CA加入受信列表;
很是簡單,將 rejectUnauthorized 設置爲 false 就行,再次運行代碼,就能夠愉快的返回頁面了。
// 例子:忽略安全警告 var https = require('https'); var fs = require('fs'); var options = { hostname: 'kyfw.12306.cn', path: '/otn/leftTicket/init', rejectUnauthorized: false // 忽略安全警告 }; var req = https.get(options, function(res){ res.pipe(process.stdout); }); req.on('error', function(err){ console.error(err.code); });
這裏包含3個步驟:
下載 12306 的CA證書
將der格式的CA證書,轉成pem格式
修改node https的配置
在12306的官網上,提供了CA證書的下載地址,將它保存到本地,命名爲 srca.cer。
https初始化client時,提供了 ca 這個配置項,能夠將 12306 的CA證書添加進去。當你訪問 12306 的網站時,client就會用ca配置項裏的 ca 證書,對當前的證書進行校驗,因而就校驗經過了。
須要注意的是,ca 配置項只支持 pem 格式,而從12306官網下載的是der格式的。須要轉換下格式才能用。關於 pem、der的區別,可參考 這裏。
openssl x509 -in srca.cer -inform der -outform pem -out srca.cer.pem
修改後的代碼以下,如今能夠愉快的訪問12306了。
// 例子:將12306的CA證書,加入咱們的信任列表裏 var https = require('https'); var fs = require('fs'); var ca = fs.readFileSync('./srca.cer.pem'); var options = { hostname: 'kyfw.12306.cn', path: '/otn/leftTicket/init', ca: [ ca ] }; var req = https.get(options, function(res){ res.pipe(process.stdout); }); req.on('error', function(err){ console.error(err.code); });
Why is my node.js SSL connection failing to connect?
DER vs. CRT vs. CER vs. PEM Certificates and How To Convert Them