Node.js學習之路13——HTTP與HTTPS

4. HTTPHTTPS的區別

  • HTTPS服務器使用HTTPS協議,HTTP服務器使用HTTP協議.
  • HTTPS服務器須要向證書受權(Certificate Authority)中心申請證書,通常免費證書何紹須要交費.在少量讀客戶端有要求的狀況下,也會要求客戶端使用證書.
  • HTTP服務器於客戶端之間傳輸的是明文數據,而HTTPS服務器於客戶端之間傳輸的是通過SSL安全加密後的密文數據.
  • HTTP服務器一般使用808080端口,HTTPS服務器使用443端口.

5. 建立HTTPS服務器

5.1 前提條件——準備公鑰私鑰和證書

建立HTTPS服務器之間,服務器端首先須要建立公鑰,私鑰及證書javascript

  • 建立公鑰,可使用openssl工具建立私鑰openssl genrsa -out privatekey.pem 1024
  • 建立證書籤名請求(Certificate Signing Request)文件openssl req -new -key privatekey.pem -out certreques.csr
  • 獲取證書,證書應該是一個通過證書受權中心簽名的文件,該證書文件內寶藍了服務器端提供的公鑰以及證書的頒發機構等信息openssl x509 -req -in certrequest.csr -signkey privatekey.pem -out certificate.pem,x509表明該證書如何國際電信聯盟制定的數字證書標準

在客戶端與服務器端創建鏈接後,將首先確認證書的合法性,若是在服務器中使用學習或測試用證書,使用瀏覽器訪問該服務器時,瀏覽器中將先顯示一個警告信息,警告用戶該證書不是一個通過證書受權中心簽名的證書.
在具有了證書文件以後,可使用該證書文件建立一個pfx文件,所謂的pfx文件,是指該文件內容必須符合公鑰加密技術12號標準(Public Key Cryptography Standards #12, PKCS#12)爲存儲和傳輸用戶或服務器私鑰,公鑰和證書而指定的格式.
+. 在openssl工具中,能夠建立pfx文件openssl pkcs12 -export -in certificate.pem -inkey privatekey.pem -out certificate.pfx
在這些文件都具有了以後,可使用HTTPS模塊中的createServer方法建立一個HTTPS服務器HTTPS.createServer(options, [requestListener(request, response)])html

5.2 開始建立HTTPS服務器

  • HTTPS.createServer(options)
  • options爲一個對象,使用的屬性及屬性值以下所示java

    • pfx: 屬性值爲一個字符串或一個Buffer對象,用於指定從pfx文件讀取出的私鑰,公鑰及證書,使用該屬性值不須要指定key屬性值,cert屬性值以及ca屬性值.
    • key: 屬性值爲一個字符串或一個Buffer對象,用於指定從後綴名爲pem的私鑰文件中讀取出來的私鑰,該屬性值爲必須指定屬性值,除非指定了pfx屬性值
    • passphrase: 屬性值爲一個自飛船,用於爲私鑰文件或pfx文件指定密碼
    • cert: 屬性值爲一個字符串或一個Buffer對象,用於指定從後綴名爲pem的文件中讀物出來的公鑰,該屬性值爲必須指定屬性值,除非指定了pfx屬性值
    • ca: 屬性值爲一個字符串或一個Buffer對象數組,用於指定一組證書,默認屬性值爲幾個著名的證書受權認證中心,好比VerlSign
    • crl: 屬性值爲一個字符串或一個Buffer對象數組,用於指定證書吊銷列表
    • ciphers: 屬性值爲一個字符串值,用於描述須要使用或取消使用的密碼.爲了阻擋BEAST攻擊,推薦獎ciphers屬性與honorCipherOrder屬性結合使用,以指定非CBC(Cipher-block chaining,密碼分組連接)模式的密碼優先級,默認屬性值爲AES128-GCM-SHA256: RC4: HIGH: !MD5: !aNULL: !EDH
    • handshakeTimeout: 屬性值爲一個整數,用於指定多少秒內若是沒有完成客戶端與服務器之間的握手,則放棄本次鏈接,默認屬性值爲120s.當在指定時間內沒有完成握手時,將處罰HTTPS服務器的clientError事件.
    • honorCipherOrder: 屬性值爲一個布爾值,當屬性值指定爲true時,服務器將密碼列表發送給客戶端,有客戶端選擇密碼,儘管該屬性值默認爲false,可是仍推薦獎該屬性值設置爲true,以阻止BEAST攻擊
    • requestCert: 屬性值爲一個布爾值,當屬性值指定爲true時,服務器在確認鏈接時要求客戶端提供證書,默認屬性值爲false
    • rejectUnauthorized:屬性值爲一個布爾值,若是屬性值爲true,那麼服務器拒絕任何不能提供服務器端所要求的證書的客戶端.只有當requestCert屬性值指定爲true時,該屬性值纔有效,默認屬性值爲false
    • NPNProtocols: 屬性值爲一個數組或一個Buffer對象,用於指定服務器端所需使用的NPN協議(這些協議應該按照其優先級排序).NPN(Next Protocol Negotiation)協議是一種用於指定服務器可使用多種協議(包括HTTP,SPDY協議等)的協議
    • sessionIdContext: 屬性值指定爲true,那麼默認屬性值爲一個MD5散列值,若是requestCert屬性值指定爲false,不提供默認屬性值

5.3 建立https服務器

  • 生成私鑰key文件openssl genrsa 1024 > /root/https/private.pem
  • 經過私鑰文件生成CSR證書籤名openssl req -new -key /root/https/private.pem -out csr.pem
  • 經過私鑰文件和CSR證書籤名生成證書文件openssl x509 -req -days 365 -in csr.pem -signkey /root/https/private.pem -out /root/https/file.crt
  • app.js文件代碼
let app = require('express')();
const fs = require('fs');
const http = require('http');
const https = require('https');
const privateKey  = fs.readFileSync('/root/https/private.pem', 'utf8');
const certificate = fs.readFileSync('/root/https/file.crt', 'utf8');
const credentials = {key: privateKey, cert: certificate};

const httpServer = http.createServer(app);
const httpsServer = https.createServer(credentials, app);
const PORT = 18080;
const SSLPORT = 18081;

httpServer.listen(PORT, function() {
    console.log('HTTP Server is running on: http://localhost:%s', PORT);
});
httpsServer.listen(SSLPORT, function() {
    console.log('HTTPS Server is running on: https://localhost:%s', SSLPORT);
});

// Welcome
app.get('/', function(req, res) {
    if(req.protocol === 'https') {
        res.status(200).send('Welcome to Safety Land!');
    }
    else {
        res.status(200).send('Welcome!');
    }
});

6. 使用HTTPS向其餘網站請求數據

  • HTTPS模塊中,可使用request方法向其餘使用HTTPS協議的網站請求數據

let req = https.request(options, callback(res){})git

  • options爲一個對象或字符串,用於指定請求的目標的URL地址,若是該參數值爲一個字符串,將自動使用URL模塊中的parse方法轉換爲一個對象.在options參數值對象或使用parse方法轉換後對象中,能夠指定的屬性及屬性值以下所示github

    • host: 用於指定域名或目標主機的IP地址,默認屬性爲localhost
    • hostname: 用於指定域名或目標主機的IP地址,默認屬性爲localhost, 若是hostname屬性值與host屬性值都被指定,優先使用hostname屬性值
    • port: 指定目標服務器用於HTTP客戶單鏈接的端口號,默認爲443
    • method: 用於指定HTTP請求方式,默認爲GET
    • path: 用於指定請求路徑及查詢字符串,默認爲/
    • headers: 用於指定客戶端請求頭對象
    • auth: 用於指定認證信息部分,例如user:password
    • `agent: 用於指定用戶代理
  • 當在options參數值對象中使用以下所示的屬性及屬性值時,不能使用全局https.Agent對象chrome

    • pfx: 屬性值爲一個字符串或一個Buffer對象,用於指定從pfx文件讀取出的私鑰,公鑰及證書,使用該屬性值不須要指定key屬性值,cert屬性值以及ca屬性值.
    • key: 屬性值爲一個字符串或一個Buffer對象,用於指定從後綴名爲pem的私鑰文件中讀取出來的私鑰,該屬性值爲必須指定屬性值,除非指定了pfx屬性值
    • passphrase: 屬性值爲一個字符串,用於爲私鑰文件或pfx文件指定密碼
    • cert: 屬性值爲一個字符串或一個Buffer對象,用於指定從後綴名爲pem的文件中讀物出來的公鑰,該屬性值爲必須指定屬性值,除非指定了pfx屬性值
    • ca: 屬性值爲一個字符串或一個Buffer對象數組,用於指定一組證書,默認屬性值爲幾個著名的證書受權認證中心,好比VerlSign
    • crl: 屬性值爲一個字符串或一個Buffer對象數組,用於指定證書吊銷列表
    • ciphers: 屬性值爲一個字符串值,用於描述須要使用或取消使用的密碼.爲了阻擋BEAST攻擊,推薦獎ciphers屬性與honorCipherOrder屬性結合使用,以指定非CBC(Cipher-block chaining,密碼分組連接)模式的密碼優先級,默認屬性值爲AES128-GCM-SHA256: RC4: HIGH: !MD5: !aNULL: !EDH
    • rejectUnauthorized:屬性值爲一個布爾值,若是屬性值爲true,那麼服務器在客戶端創建鏈接後,返回響應前首先驗證客戶端提交的證書,若是驗證失敗,觸發客戶端請求對象的error事件.

7. 建立HTTPS客戶端

const https = require('https');
let options = {
    hostname: 'github.com',
    port: 443,
    path: '/',
    method: 'GET',
    agent: false
}
let req = https.get(options, (res) => {
    console.log('狀態碼:' + res.statusCode);
    console.log('響應頭:' + JSON.stringify(res.headers));
    res.setEncoding('utf8');
    res.on('data', (chunk) => {
        console.log('響應內容:' + chunk);
    });
});

req.setTimeout(1000, (res) => {
    res.abort();
});

req.on('error',  (err) => {
    if (err.code === 'ECONNRESET') {
        console.log('socket端口超時');
    } else {
        console.log('在請求數據過程當中發生錯誤,錯誤代碼爲:' + err.code)
    }
});
/**
* 狀態碼:200
* 響應頭:{
          "date": "Sun, 25 Feb 2018 14:24:24 GMT",
          "content-type": "text/html; charset=utf-8",
          "transfer-encoding": "chunked",
          "connection": "close",
          "server": "GitHub.com",
          "status": "200 OK",
          "cache-control": "no-cache",
          "vary": "X-PJAX, Accept-Encoding",
          "x-ua-compatible": "IE=Edge,chrome=1",
          "set-cookie": ["logged_in=no; domain=.github.com; path=/; expires=Thu, 25 Feb 2038 14:24:24 -0000; secure; HttpOnly", "_gh_sess=eyJzZXNzaW9uX2lkIjoiMDY1YjM2ZmU4ZGM5MTFlZTliNjllMDI5ZDg0YzQ0ODUiLCJsYXN0X3JlYWRfZnJvbV9yZXBsaWNhcyI6MTUxOTU2ODY2NDUzMywiX2NzcmZfdG9rZW4iOiJ1ck5qWmZTMkpkeGpxMlN2ZzJhbklJM2pvaTJMVWEzWHcvSXEvTGtzVzBrPSJ9--8b5c0c203b3767a35f046b5ea4e375715e4d95be; path=/; secure; HttpOnly"],
          "x-request-id": "1faefb3e691e8adc7e1a7d727c07236f",
          "x-runtime": "0.050658",
          "expect-ct": "max-age=2592000, report-uri=\"https://api.github.com/_private/browser/errors\"",
          "content-security-policy": "default-src 'none'; base-uri 'self'; block-all-mixed-content; child-src render.githubusercontent.com; connect-src 'self' uploads.github.com status.github.com collector.githubapp.com api.github.com www.google-analytics.com github-cloud.s3.amazonaws.com github-production-repository-file-5c1aeb.s3.amazonaws.com github-production-upload-manifest-file-7fdce7.s3.amazonaws.com github-production-user-asset-6210df.s3.amazonaws.com wss://live.github.com; font-src assets-cdn.github.com; form-action 'self' github.com gist.github.com; frame-ancestors 'none'; img-src 'self' data: assets-cdn.github.com identicons.github.com collector.githubapp.com github-cloud.s3.amazonaws.com *.githubusercontent.com; manifest-src 'self'; media-src 'none'; script-src assets-cdn.github.com; style-src 'unsafe-inline' assets-cdn.github.com; worker-src 'self'",
          "strict-transport-security": "max-age=31536000; includeSubdomains; preload",
          "x-content-type-options": "nosniff",
          "x-frame-options": "deny",
          "x-xss-protection": "1; mode=block",
          "x-runtime-rack": "0.058378",
          "x-github-request-id": "1B82:60FF:117094:18A2C0:5A92C717"
      }
* 
****/
相關文章
相關標籤/搜索