隨着互聯網快速發展,互聯網信息安全愈來愈受到你們重視,HTTPS
應該是近兩年各大廠商都在盡力普及的技術之一。國內大廠基本上已經全面普及了 HTTPS。html
本文首發於個人我的網站:據說 - tasaid.com/,建議在個人我的網站閱讀,擁有更好的閱讀體驗。前端
前端開發 QQ 羣:377786580git
早在 2016 年末,我就寫過 《 從 HTTP 到 HTTPS 系列 》文章來說解 HTTPS
。當時結合本站的部署經驗,給你們詳細介紹了 《 IIS 部署免費 HTTPS 》。github
這篇文章就跟你們介紹一下 Node.js
如何部署免費 HTTPS
以及簡單的部署 HTTP/2
。web
截止 2018 年 03 月 13 日,由 Let's Encrypt 實時統計報告 顯示,在統計的 6930 多萬活躍網站中,已經有 5350 萬(約 77%)的站點部署了 HTTPS
證書服務。chrome
同時 Google 透明度報告 - 網絡上的 HTTPS 加密 中,統計了使用 Chrome 瀏覽器,訪問的站點統計中,HTTPS 使用率的增加狀況:typescript
而在今年 2 月份,Chrome 團隊也宣佈,將在 2018 年 7 月份發佈的 Chrome 68 中,將沒有部署 HTTPS 的網站標記爲 "不安全"。shell
簡而言之,HTTPS 大勢所趨。express
早在 《 從 HTTP 到 HTTPS - IIS 部署免費 HTTPS 》一文中,我就指出了 Let's Encrypt 免費證書的優點:npm
由 ISRG(Internet Security Research Group,互聯網安全研究小組)提供服務,免費、訪問速度快,穩定等。
因此此次部署的證書也是圍繞 Let's Encrypt
展開。
因爲 js 生態圈的繁華,因此想找一個現有的包是件很輕鬆的事情,greenlock-express 這個包就幫助咱們封裝了 Let's Enctrypt
證書的部署,只須要引入這個包並使用,就能夠:
Let's Encrypt
證書而且 greenlock
相關的證書生態圈十分完善,一樣有支持 koa
的 greenlock-koa。
經過 npm
安裝 greenlock-express
:
$ npm install --save greenlock-express@2.x
複製代碼
使用起來很是簡單,這是 greenlock-express
默認提供的 demo:
const greenlock = require('greenlock-express')
require('greenlock-express').create({
// 測試
server: 'staging',
// 聯繫郵箱
email: 'john.doe@example.com',
// 是否贊成 Let's Encrypt 條款... 這必須爲 true 啊,否則走不下去
agreeTos: true,
// 申請的域名列表,不支持通配符
approveDomains: [ 'tasaid.com', 'www.tasaid.com' ],
// 綁定 express app
app: require('express')().use('/', function (req, res) {
res.end('Hello, World!');
})
}).listen(80, 443)
複製代碼
證書存在 ~/letsencrypt
。
固然上面代碼只能用於測試/開發環境,由於它並無申請一個有效的證書,而是生成了一個自簽名的證書(跟之前的 12306 自簽證書同樣),用於在開發環境中調試。
greenlock-express
的 create(options)
函數參數簽名以下:
interface Options {
/** * Express app */
app: Express
/* * 遠程服務器 * 測試環境中可用爲 staging * 生產環境中爲 https://acme-v01.api.letsencrypt.org/directory */
server: string
/** * 用於接收 let's encrypt 協議的郵箱 */
email: string
/** * 是否贊成協議 */
agreeTos: boolean
/** * 在註冊域名獲取證書前,會執行這個回調函數 * string[]: 一組須要註冊證書的域名 * 函數: 第一個參數跟 Options 格式差很少,第二個參數是當前自動獲取的域名信息,第三個參數是在處理完以後傳遞的回調函數 */
approveDomains: string[] | (opts, certs: cb) => any
/** * 更新證書最大天數 (以毫秒爲單位) */
renewWithin: number
/** * 更新證書的最小天數(以毫秒爲單位) */
renewBy: number
}
複製代碼
通過測試,在真實的生產環境中, approveDomains
必須爲函數,傳數組的話不會生效。
生產環境中部署還須要作一些配置改動和引入一些包。
更新包:
$ npm i --save greenlock-express@2.x
$ npm i --save le-challenge-fs
$ npm i --save le-store-certbot
$ npm i --save redirect-https
複製代碼
生產代碼:
const greenlock = require('greenlock-express')
const express = require('express')
const app = express()
const lex = greenlock.create({
// 注意這裏要成這個固定地址
server: 'https://acme-v01.api.letsencrypt.org/directory',
challenges: {
'http-01': require('le-challenge-fs').create({ webrootPath: '~/letsencrypt/var/acme-challenges' })
},
store: require('le-store-certbot').create({
webrootPath: '~/letsencrypt/srv/www/:hostname/.well-known/acme-challenge'
}),
approveDomains: (opts: any, certs: any, cb: any) => {
appLog.info('approveDomains', { opts, certs })
if (certs) {
/* * 注意這裏若是是這樣寫的話,必定要對域名作校驗 * 不然其餘人能夠經過將域名指向你的服務器地址,致使你註冊了其餘域名的證書 * 從而形成安全性問題 */
// opts.domains = certs.altnames
opts.domains = [ 'tasaid.com', 'www.tasaid.com' ]
} else {
opts.email = '你的郵箱@live.com'
opts.agreeTos = true
}
cb(null, { options: opts, certs: certs })
},
})
// 這裏的 redirect-https 用於自動將 HTTP 請求跳到 HTTPS 上
require('http').createServer(
lex.middleware(
require('redirect-https')()
)
).listen(80, function () {
console.log('Listening', `for ACME http-01 challenges on: ${JSON.stringify(this.address())}`)
})
// 綁定 HTTPS 端口
require('https').createServer(
lex.httpsOptions,
lex.middleware(app)
).listen(443, function () {
console.log(('App is running at http://localhost:%d in %s mode'), app.get('port'), app.get('env'))
console.log('Press CTRL-C to stop\n')
})
複製代碼
若是沒有生效,能夠檢查下 ~/letsencrypt
的證書信息,和 443 端口是否打開。
HTTP/2 是 HTTP/1.1 的升級版,主要來講改進了這些地方:
值的注意的是,HTTP/2 是支持 HTTP 協議的,只不過瀏覽器廠商都不肯意支持 HTTP,因此基本上能夠認爲,用上 HTTP/2 的前置條件是必須部署 HTTPS。
早在 2009 年,Google 開發了一個實驗性協議,叫作 SPDY,目的解決 HTTP/1.x 中的一些設計缺陷。在 SPDY 發佈幾年後,這個新的實驗性協議獲得了 Chrome、Firefox 和 Opera 的支持,應用愈來愈普遍。而後 HTTP 工做組 (HTTP-WG) 在這個 SPDY 的基礎上,設計了 HTTP/2,因此能夠說 SPDY 是 HTTP/2 的前身。
關於 HTTP/2 的詳情能夠參考 這篇文章。
引入 HTTP/2
在 Node.js
中也十分簡單,只須要引入 spdy
包便可:
$ npm i --save spdy
複製代碼
而後咱們把上一節的代碼作一點修改便可支持 HTTP/2:
const greenlock = require('greenlock-express')
const express = require('express')
// HTTP/2
const spdy = require('spdy')
const app = express()
const lex = greenlock.create({
// 注意這裏要成這個固定地址
server: 'https://acme-v01.api.letsencrypt.org/directory',
challenges: {
'http-01': require('le-challenge-fs').create({ webrootPath: '~/letsencrypt/var/acme-challenges' })
},
store: require('le-store-certbot').create({
webrootPath: '~/letsencrypt/srv/www/:hostname/.well-known/acme-challenge'
}),
approveDomains: (opts: any, certs: any, cb: any) => {
appLog.info('approveDomains', { opts, certs })
if (certs) {
/* * 注意這裏若是是這樣寫的話,必定要對域名作校驗 * 不然其餘人能夠經過將域名指向你的服務器地址,致使你註冊了其餘域名的證書 * 從而形成安全性問題 */
// opts.domains = certs.altnames
opts.domains = [ 'tasaid.com', 'www.tasaid.com' ]
} else {
opts.email = '你的郵箱@live.com'
opts.agreeTos = true
}
cb(null, { options: opts, certs: certs })
},
})
// 這裏的 redirect-https 用於自動將 HTTP 請求跳到 HTTPS 上
require('http').createServer(
lex.middleware(
require('redirect-https')()
)
).listen(80, function () {
console.log('Listening', `for ACME http-01 challenges on: ${JSON.stringify(this.address())}`)
})
// HTTP/2
spdy.createServer(lex.httpsOptions, lex.middleware(app)).listen(443, function () {
console.log('Listening https', `for ACME tls-sni-01 challenges and serve app on: ${JSON.stringify(this.address())}`)
})
複製代碼
至於 HTTP/2 相關的技術應用,會在後續篇幅中再爲你們講解。
本文首發於個人我的網站:據說 - tasaid.com/,建議在個人我的網站閱讀,擁有更好的閱讀體驗。
前端開發 QQ 羣:377786580