node.js - urlencoded - response render express




如何在Express.js中強制使用SSL/https (6)

http.createServer(app.handle)。聽(80)

https.createServer(options,app.handle).listen(443)

快遞2x

我正在嘗試為Express.js創建一個中間件,將所有非安全(端口80)流量重定向到安全的SSL端口(443)。 不幸的是,Express.js請求中沒有信息可以讓您確定請求是通過http還是https。

一種解決方案是重定向每個請求,但這不是我的選擇。

筆記:

  1. 使用Apache或其他方法無法處理它。 它必須在節點中完成。

  2. 在應用程序中只能啟動一個服務器。

你會如何解決這個問題?


試試這個例子:

var express = require('express');
        var app = express();
        // set up a route to redirect http to https
        app.use(function (req, res, next) {
        if (!/https/.test(req.protocol)) {
            res.redirect("https://" + req.headers.host + req.url);
        } else {
            return next();
        }
        });
        var webServer = app.listen(port, function () {
            console.log('Listening on port %d', webServer.address().port);
        });


萬一你在Heroku上託管並且只想重定向到HTTPS而不管端口,這裡是我們正在使用的中間件解決方案。

如果您在本地開發,它不會重新定向。

function requireHTTPS(req, res, next) {
  // The 'x-forwarded-proto' check is for Heroku
  if (!req.secure && req.get('x-forwarded-proto') !== 'https' && process.env.NODE_ENV !== "development") {
    return res.redirect('https://' + req.get('host') + req.url);
  }
  next();
}

您可以像Express(2.x和4.x)一樣使用它:

app.use(requireHTTPS);

雖然問題看起來已經有一年了,但我想回答一下,因為它可能對其他人有所幫助。 使用最新版本的expressjs(2.x)實際上非常簡單。 首先使用此代碼創建密鑰和證書

openssl genrsa -out ssl-key.pem 1024

$ openssl req -new -key ssl-key.pem -out certrequest.csr ..一堆提示

$ openssl x509 -req -in certrequest.csr -signkey ssl-key.pem -out ssl-cert.pem

將證書和密鑰文件存儲在包含app.js的文件夾中。 然後編輯app.js文件並在express.createServer()之前編寫以下代碼

var https = require('https');
var fs = require('fs');

var sslkey = fs.readFileSync('ssl-key.pem');
var sslcert = fs.readFileSync('ssl-cert.pem')

var options = {
    key: sslkey,
    cert: sslcert
};

現在傳遞createServer()函數中的options對象

express.createServer(options);

完成!


首先,讓我看看我是否可以澄清問題。 您只能使用一(1)個node.js進程,但該進程可以偵聽兩(2)個網絡端口,包括80和443,對嗎? (當您說一台服務器時,不清楚您是指一個進程還是僅一個網絡端口)。

鑑於這種約束,你問題似乎是,由於你沒有提供的原因,你的客戶端以某種方式連接到錯誤的端口。 這是一個奇怪的邊緣情況,因為默認情況下,客戶端將向端口80和HTTPS發出HTTP請求到端口443.當我說“默認情況下”時,我的意思是如果URL中沒有包含特定端口。 因此,除非您明確使用像http://example.com:443https://example.com:80這樣的縱橫交錯的網址,否則您的網站確實不應該有任何縱橫交錯的流量。 但是既然你問了這個問題,我想你必須擁有它,雖然我打賭你使用的是非標準端口而不是80/443默認端口。

因此,對於背景:是的,一些Web服務器處理得相當好。 例如,如果您執行http://example.com:443到nginx,它將響應HTTP 400“錯誤請求”響應,指示“普通HTTP請求已發送到HTTPS端口”。 是的,您可以從同一個node.js進程中偵聽80和443。 您只需要創建2個單獨的express.createServer()實例,這樣就沒問題了。 這是一個簡單的程序來演示處理這兩種協議。

var fs = require("fs");
var express = require("express");

var http = express.createServer();

var httpsOptions = {
  key: fs.readFileSync('key.pem'),
  cert: fs.readFileSync('cert.pem')
};

var https = express.createServer(httpsOptions);

http.all('*', function(req, res) {
  console.log("HTTP: " + req.url);
  return res.redirect("https://" + req.headers["host"] + req.url);
});

http.error(function(error, req, res, next) {
  return console.log("HTTP error " + error + ", " + req.url);
});

https.error(function(error, req, res, next) {
  return console.log("HTTPS error " + error + ", " + req.url);
});

https.all('*', function(req, res) {
  console.log("HTTPS: " + req.url);
  return res.send("Hello, World!");
});

http.listen(80);

我可以通過cURL測試這個:

$ curl --include --silent http://localhost/foo
HTTP/1.1 302 Moved Temporarily
X-Powered-By: Express
Content-Type: text/html
Location: https://localhost/foo
Connection: keep-alive
Transfer-Encoding: chunked

<p>Moved Temporarily. Redirecting to <a href="https://localhost/foo">https://localhost/foo</a></p>

$ curl --include --silent --insecure https://localhost:443/foo
HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: text/html; charset=utf-8
Content-Length: 13
Connection: keep-alive

Hello, World!%

並顯示從HTTP到HTTPS的重定向...

curl --include --silent --location --insecure 'http://localhost/foo?bar=bux'
HTTP/1.1 302 Moved Temporarily
X-Powered-By: Express
Content-Type: text/html
Location: https://localhost/foo?bar=bux
Connection: keep-alive
Transfer-Encoding: chunked

HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: text/html; charset=utf-8
Content-Length: 13
Connection: keep-alive

Hello, World!%

因此,這將適用於常規案例的兩個協議並正確地重定向。 但是,十字架根本不起作用。 我相信一個快速交叉的請求命中快速服務器不會通過中間件堆棧路由,因為它從一開始就被視為錯誤,甚至不會正確解析請求URI,這是必要的通過路由中間件鏈發送它。 快速堆棧甚至沒有得到它們我認為因為它們不是有效請求,所以它們在節點TCP堆棧中的某處被忽略。 可能編寫一個服務器來執行此操作,並且可能已經有一個模塊,但您必須直接在TCP層編寫它。 而且您必須在第一塊客戶端數據中檢測到常規HTTP請求,這些客戶端數據訪問TCP端口並將該連接連接到HTTP服務器而不是正常的TLS握手。

當我執行其中任何一個時,我的快速錯誤處理程序不會被調用。

curl  --insecure https://localhost:80/foo
curl: (35) Unknown SSL protocol error in connection to localhost:80

curl http://localhost:443/foo
curl: (52) Empty reply from server




express