使用 node.js/express 自动 HTTPS 连接/重定向

发布于 2024-12-04 21:57:48 字数 1055 浏览 2 评论 0原文

我一直在尝试使用我正在开发的 node.js 项目设置 HTTPS。对于这个示例,我基本上遵循了 node.js 文档

// curl -k https://localhost:8000/
var https = require('https');
var fs = require('fs');

var options = {
  key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'),
  cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem')
};

https.createServer(options, function (req, res) {
  res.writeHead(200);
  res.end("hello world\n");
}).listen(8000);

现在,当我这样做

curl -k https://localhost:8000/

时得到

hello world

预期的结果。但如果我这样做的话

curl -k http://localhost:8000/

,回想起来,

curl: (52) Empty reply from server

这似乎很明显,它会以这种方式工作,但与此同时,最终访问我的项目的人不会输入 https://yadayada,我希望所有流量从访问该网站的那一刻起都是 https。

如何让节点(以及 Express,因为这是我正在使用的框架)将所有传入流量移交给 https,无论是否指定?我找不到任何解决此问题的文档。或者只是假设在生产环境中,节点前面有一些东西(例如nginx)来处理这种重定向?

这是我第一次涉足网络开发,所以如果这是显而易见的事情,请原谅我的无知。

I've been trying to get HTTPS set up with a node.js project I'm working on. I've essentially followed the node.js documentation for this example:

// curl -k https://localhost:8000/
var https = require('https');
var fs = require('fs');

var options = {
  key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'),
  cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem')
};

https.createServer(options, function (req, res) {
  res.writeHead(200);
  res.end("hello world\n");
}).listen(8000);

Now, when I do

curl -k https://localhost:8000/

I get

hello world

as expected. But if I do

curl -k http://localhost:8000/

I get

curl: (52) Empty reply from server

In retrospect this seems obvious that it would work this way, but at the same time, people who eventually visit my project aren't going to type in https://yadayada, and I want all traffic to be https from the moment they hit the site.

How can I get node (and Express as that is the framework I'm using) to hand off all incoming traffic to https, regardless of whether or not it was specified? I haven't been able to find any documentation that has addressed this. Or is it just assumed that in a production environment, node has something that sits in front of it (e.g. nginx) that handles this kind of redirection?

This is my first foray into web development, so please forgive my ignorance if this is something obvious.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(23

半衬遮猫 2024-12-11 21:57:48

瑞安,谢谢你为我指明了正确的方向。我用一些代码充实了你的答案(第二段),它有效。在这种情况下,这些代码片段被放入我的express应用程序中:

// set up plain http server
var http = express();

// set up a route to redirect http to https
http.get('*', function(req, res) {  
    res.redirect('https://' + req.headers.host + req.url);

    // Or, if you don't want to automatically detect the domain name from the request header, you can hard code it:
    // res.redirect('https://example.com' + req.url);
})

// have it listen on 8080
http.listen(8080);

https express服务器在3000上侦听ATM。我设置了这些iptables规则,以便节点不必以root身份运行:

iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8080
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 443 -j REDIRECT --to-port 3000

总之,这完全按照我想要的方式工作到。

要防止通过 HTTP 窃取 Cookie,请参阅此答案< /a> (来自注释)或使用以下代码:

const session = require('cookie-session');
app.use(
  session({
    secret: "some secret",
    httpOnly: true,  // Don't let browser javascript access cookies.
    secure: true, // Only use cookies over https.
  })
);

Ryan, thanks for pointing me in the right direction. I fleshed out your answer (2nd paragraph) a little bit with some code and it works. In this scenario these code snippets are put in my express app:

// set up plain http server
var http = express();

// set up a route to redirect http to https
http.get('*', function(req, res) {  
    res.redirect('https://' + req.headers.host + req.url);

    // Or, if you don't want to automatically detect the domain name from the request header, you can hard code it:
    // res.redirect('https://example.com' + req.url);
})

// have it listen on 8080
http.listen(8080);

The https express server listens ATM on 3000. I set up these iptables rules so that node doesn't have to run as root:

iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8080
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 443 -j REDIRECT --to-port 3000

All together, this works exactly as I wanted it to.

To prevent theft of cookies over HTTP, see this answer (from the comments) or use this code:

const session = require('cookie-session');
app.use(
  session({
    secret: "some secret",
    httpOnly: true,  // Don't let browser javascript access cookies.
    secure: true, // Only use cookies over https.
  })
);
预谋 2024-12-11 21:57:48

感谢这个人:
https://www.tonyerwin.com/2014 /09/redirecting-http-to-https-with-nodejs.html

如果安全,则通过 https 请求,否则重定向到 https

app.enable('trust proxy')
app.use((req, res, next) => {
    req.secure ? next() : res.redirect('https://' + req.headers.host + req.url)
})

Thanks to this guy:
https://www.tonyerwin.com/2014/09/redirecting-http-to-https-with-nodejs.html

If secure, requests via https, otherwise redirects to https

app.enable('trust proxy')
app.use((req, res, next) => {
    req.secure ? next() : res.redirect('https://' + req.headers.host + req.url)
})
翻身的咸鱼 2024-12-11 21:57:48

如果您遵循传统端口,因为 HTTP 默认情况下尝试端口 80,HTTPS 默认情况下尝试端口 443,您可以在同一台计算机上简单地拥有两个服务器:
代码如下:

var https = require('https');

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

https.createServer(options, function (req, res) {
    res.end('secure!');
}).listen(443);

// Redirect from http port 80 to https
var http = require('http');
http.createServer(function (req, res) {
    res.writeHead(301, { "Location": "https://" + req.headers['host'] + req.url });
    res.end();
}).listen(80);

使用 https 进行测试:

$ curl https://127.0.0.1 -k
secure!

使用 http:

$ curl http://127.0.0.1 -i
HTTP/1.1 301 Moved Permanently
Location: https://127.0.0.1/
Date: Sun, 01 Jun 2014 06:15:16 GMT
Connection: keep-alive
Transfer-Encoding: chunked

更多详细信息: 通过同一端口的 Nodejs HTTP 和 HTTPS

If you follow conventional ports since HTTP tries port 80 by default and HTTPS tries port 443 by default you can simply have two server's on the same machine:
Here's the code:

var https = require('https');

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

https.createServer(options, function (req, res) {
    res.end('secure!');
}).listen(443);

// Redirect from http port 80 to https
var http = require('http');
http.createServer(function (req, res) {
    res.writeHead(301, { "Location": "https://" + req.headers['host'] + req.url });
    res.end();
}).listen(80);

Test with https:

$ curl https://127.0.0.1 -k
secure!

With http:

$ curl http://127.0.0.1 -i
HTTP/1.1 301 Moved Permanently
Location: https://127.0.0.1/
Date: Sun, 01 Jun 2014 06:15:16 GMT
Connection: keep-alive
Transfer-Encoding: chunked

More details : Nodejs HTTP and HTTPS over same port

凉墨 2024-12-11 21:57:48

使用 Nginx,您可以利用“x-forwarded-proto”标头:

function ensureSec(req, res, next){
    if (req.headers["x-forwarded-proto"] === "https"){
       return next();
    }
    res.redirect("https://" + req.headers.host + req.url);  
}

With Nginx you can take advantage of the "x-forwarded-proto" header:

function ensureSec(req, res, next){
    if (req.headers["x-forwarded-proto"] === "https"){
       return next();
    }
    res.redirect("https://" + req.headers.host + req.url);  
}
戏剧牡丹亭 2024-12-11 21:57:48

从 0.4.12 开始,我们还没有真正干净的方式来监听 HTTP 和 HTTP 协议。使用 Node 的 HTTP/HTTPS 服务器在同一端口上进行 HTTPS。

有些人通过让 Node 的 HTTPS 服务器(也适用于 Express.js)侦听 443(或其他端口)并让一个小型 http 服务器绑定到 80 并将用户重定向到安全端口来解决这个问题。

如果您绝对必须能够在单个端口上处理这两种协议,那么您需要在该端口上放置 nginx、lighttpd、apache 或其他一些 Web 服务器,并充当 Node.js 的反向代理。

As of 0.4.12 we have no real clean way of listening for HTTP & HTTPS on the same port using Node's HTTP/HTTPS servers.

Some people have solved this issue by having having Node's HTTPS server (this works with Express.js as well) listen to 443 (or some other port) and also have a small http server bind to 80 and redirect users to the secure port.

If you absolutely have to be able to handle both protocols on a single port then you need to put nginx, lighttpd, apache, or some other web server on that port and have act as a reverse proxy for Node.

李不 2024-12-11 21:57:48

我使用 Basarat 提出的解决方案,但我还需要覆盖端口,因为我曾经有 2 个不同的 HTTP 和 HTTPS 协议端口。

res.writeHead(301, { "Location": "https://" + req.headers['host'].replace(http_port,https_port) + req.url });

我也更喜欢使用非标准端口,这样就可以在没有root权限的情况下启动nodejs。
我喜欢 8080 和 8443,因为我有多年的 tomcat 编程经验。

我的完整文件变成

var fs = require('fs');
var http = require('http');
var http_port    =   process.env.PORT || 8080; 
var app = require('express')();

// HTTPS definitions
var https = require('https');
var https_port    =   process.env.PORT_HTTPS || 8443; 
var options = {
   key  : fs.readFileSync('server.key'),
   cert : fs.readFileSync('server.crt')
};

app.get('/', function (req, res) {
   res.send('Hello World!');
});

https.createServer(options, app).listen(https_port, function () {
   console.log('Magic happens on port ' + https_port); 
});

// Redirect from http port to https
http.createServer(function (req, res) {
    res.writeHead(301, { "Location": "https://" + req.headers['host'].replace(http_port,https_port) + req.url });
    console.log("http request, will go to >> ");
    console.log("https://" + req.headers['host'].replace(http_port,https_port) + req.url );
    res.end();
}).listen(http_port);

然后我使用 iptable 在我的 HTTP 和 HTTPS 端口上转发 80 和 443 流量。

sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8080
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 443 -j REDIRECT --to-port 8443

I use the solution proposed by Basarat but I also need to overwrite the port because I used to have 2 different ports for HTTP and HTTPS protocols.

res.writeHead(301, { "Location": "https://" + req.headers['host'].replace(http_port,https_port) + req.url });

I prefer also to use not standard port so to start nodejs without root privileges.
I like 8080 and 8443 because I came from lots of years of programming on tomcat.

My complete file become

var fs = require('fs');
var http = require('http');
var http_port    =   process.env.PORT || 8080; 
var app = require('express')();

// HTTPS definitions
var https = require('https');
var https_port    =   process.env.PORT_HTTPS || 8443; 
var options = {
   key  : fs.readFileSync('server.key'),
   cert : fs.readFileSync('server.crt')
};

app.get('/', function (req, res) {
   res.send('Hello World!');
});

https.createServer(options, app).listen(https_port, function () {
   console.log('Magic happens on port ' + https_port); 
});

// Redirect from http port to https
http.createServer(function (req, res) {
    res.writeHead(301, { "Location": "https://" + req.headers['host'].replace(http_port,https_port) + req.url });
    console.log("http request, will go to >> ");
    console.log("https://" + req.headers['host'].replace(http_port,https_port) + req.url );
    res.end();
}).listen(http_port);

Then I use iptable for forwording 80 and 443 traffic on my HTTP and HTTPS ports.

sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8080
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 443 -j REDIRECT --to-port 8443
昇り龍 2024-12-11 21:57:48

您可以使用 express-force-https 模块:

npm install - -保存express-force-https

var express = require('express');
var secure = require('express-force-https');

var app = express();
app.use(secure);

You can use the express-force-https module:

npm install --save express-force-https

var express = require('express');
var secure = require('express-force-https');

var app = express();
app.use(secure);
快乐很简单 2024-12-11 21:57:48

我发现 req.protocol 在我使用express时有效(没有测试过,但我怀疑它有效)。使用当前节点 0.10.22 和 Express 3.4.3

app.use(function(req,res,next) {
  if (!/https/.test(req.protocol)){
     res.redirect("https://" + req.headers.host + req.url);
  } else {
     return next();
  } 
});

I find req.protocol works when I am using express (have not tested without but I suspect it works). using current node 0.10.22 with express 3.4.3

app.use(function(req,res,next) {
  if (!/https/.test(req.protocol)){
     res.redirect("https://" + req.headers.host + req.url);
  } else {
     return next();
  } 
});
吐个泡泡 2024-12-11 21:57:48

该答案需要更新才能与 Express 4.0 一起使用。以下是我如何让单独的 http 服务器工作:

var express = require('express');
var http = require('http');
var https = require('https');

// Primary https app
var app = express()
var port = process.env.PORT || 3000;
app.set('env', 'development');
app.set('port', port);
var router = express.Router();
app.use('/', router);
// ... other routes here
var certOpts = {
    key: '/path/to/key.pem',
    cert: '/path/to/cert.pem'
};
var server = https.createServer(certOpts, app);
server.listen(port, function(){
    console.log('Express server listening to port '+port);
});


// Secondary http app
var httpApp = express();
var httpRouter = express.Router();
httpApp.use('*', httpRouter);
httpRouter.get('*', function(req, res){
    var host = req.get('Host');
    // replace the port in the host
    host = host.replace(/:\d+$/, ":"+app.get('port'));
    // determine the redirect destination
    var destination = ['https://', host, req.url].join('');
    return res.redirect(destination);
});
var httpServer = http.createServer(httpApp);
httpServer.listen(8080);

This answer needs to be updated to work with Express 4.0. Here is how I got the separate http server to work:

var express = require('express');
var http = require('http');
var https = require('https');

// Primary https app
var app = express()
var port = process.env.PORT || 3000;
app.set('env', 'development');
app.set('port', port);
var router = express.Router();
app.use('/', router);
// ... other routes here
var certOpts = {
    key: '/path/to/key.pem',
    cert: '/path/to/cert.pem'
};
var server = https.createServer(certOpts, app);
server.listen(port, function(){
    console.log('Express server listening to port '+port);
});


// Secondary http app
var httpApp = express();
var httpRouter = express.Router();
httpApp.use('*', httpRouter);
httpRouter.get('*', function(req, res){
    var host = req.get('Host');
    // replace the port in the host
    host = host.replace(/:\d+$/, ":"+app.get('port'));
    // determine the redirect destination
    var destination = ['https://', host, req.url].join('');
    return res.redirect(destination);
});
var httpServer = http.createServer(httpApp);
httpServer.listen(8080);
小苏打饼 2024-12-11 21:57:48

如果您的应用程序位于受信任的代理(例如 AWS ELB 或正确配置的 nginx)后面,则此代码应该可以工作:

app.enable('trust proxy');
app.use(function(req, res, next) {
    if (req.secure){
        return next();
    }
    res.redirect("https://" + req.headers.host + req.url);
});

注意:

  • 这假设您在 80 和 443 上托管您的网站,如果不是,您需要更改重定向时的端口
  • 这还假设您要终止代理上的 SSL。如果您正在执行 SSL 端到端,请使用上面@basarat 的答案。端到端 SSL 是更好的解决方案。
  • app.enable('trust proxy') 允许express检查X-Forwarded-Proto标头

If your app is behind a trusted proxy (e.g. an AWS ELB or a correctly configured nginx), this code should work:

app.enable('trust proxy');
app.use(function(req, res, next) {
    if (req.secure){
        return next();
    }
    res.redirect("https://" + req.headers.host + req.url);
});

Notes:

  • This assumes that you're hosting your site on 80 and 443, if not, you'll need to change the port when you redirect
  • This also assumes that you're terminating the SSL on the proxy. If you're doing SSL end to end use the answer from @basarat above. End to end SSL is the better solution.
  • app.enable('trust proxy') allows express to check the X-Forwarded-Proto header
墨落成白 2024-12-11 21:57:48

这里的大多数答案建议使用 req.headers.host 标头。

Host 标头是 HTTP 1.1 所必需的,但它实际上是可选的,因为该标头可能实际上不是由 HTTP 客户端发送的,并且 node/express 将接受此请求。

您可能会问:哪个 HTTP 客户端(例如:浏览器)可以发送缺少该标头的请求? HTTP 协议非常简单。您可以用几行代码编写一个 HTTP 请求,而不发送主机标头,如果每次收到格式错误的请求时都会抛出异常,并且根据您处理此类异常的方式,这可能会导致您的服务器瘫痪。

因此始终验证所有输入。这不是偏执,我收到过在我的服务中缺少主机标头的请求。

另外,切勿将 URL 视为字符串。使用节点 url 模块修改字符串的特定部分。将 URL 视为字符串可以通过多种方式加以利用。不要这样做。

Most answers here suggest to use the req.headers.host header.

The Host header is required by HTTP 1.1, but it is actually optional since the header might not be actually sent by a HTTP client, and node/express will accept this request.

You might ask: which HTTP client (e.g: browser) can send a request missing that header? The HTTP protocol is very trivial. You can craft a HTTP request in few lines of code, to not send a host header, and if each time you receive a malformed request you throw an exception, and depending on how you handle such exceptions, this can take your server down.

So always validate all input. This is not paranoia, I have received requests lacking the host header in my service.

Also, never treat URLs as strings. Use the node url module to modify specific parts of a string. Treating URLs as strings can be exploited in many many many ways. Don't do it.

jJeQQOZ5 2024-12-11 21:57:48

你可以使用“net”模块来监听HTTP和HTTP协议。同一端口上的 HTTPS

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

var net=require('net');
var handle=net.createServer().listen(8000)

var options = {
  key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'),
  cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem')
};

https.createServer(options, function (req, res) {
  res.writeHead(200);
  res.end("hello world\n");
}).listen(handle);

http.createServer(function(req,res){
  res.writeHead(200);
  res.end("hello world\n");
}).listen(handle)

you can use "net" module to listening for HTTP & HTTPS on the same port

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

var net=require('net');
var handle=net.createServer().listen(8000)

var options = {
  key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'),
  cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem')
};

https.createServer(options, function (req, res) {
  res.writeHead(200);
  res.end("hello world\n");
}).listen(handle);

http.createServer(function(req,res){
  res.writeHead(200);
  res.end("hello world\n");
}).listen(handle)
平安喜乐 2024-12-11 21:57:48
var express = require('express');
var app = express();

app.get('*',function (req, res) {
    res.redirect('https://<domain>' + req.url);
});

app.listen(80);

这就是我们使用的并且效果很好!

var express = require('express');
var app = express();

app.get('*',function (req, res) {
    res.redirect('https://<domain>' + req.url);
});

app.listen(80);

This is what we use and it works great!

段念尘 2024-12-11 21:57:48

这对我有用:

app.use(function(req,res,next) {
    if(req.headers["x-forwarded-proto"] == "http") {
        res.redirect("https://[your url goes here]" + req.url, next);
    } else {
        return next();
    } 
});

This worked for me:

app.use(function(req,res,next) {
    if(req.headers["x-forwarded-proto"] == "http") {
        res.redirect("https://[your url goes here]" + req.url, next);
    } else {
        return next();
    } 
});
入画浅相思 2024-12-11 21:57:48

您可以实例化 2 个 Node.js 服务器 - 一个用于 HTTP 和 HTTPS

您还可以定义两个服务器都将执行的设置函数,这样您就不必编写太多重复的代码。

这是我的做法:(使用restify.js,但也应该适用于express.js,或节点本身)

http://qugstart.com/blog/node-js/node-js-restify-server-with-both-http-and- https/

You can instantiate 2 Node.js servers - one for HTTP and HTTPS

You can also define a setup function that both servers will execute, so that you don't have to write much duplicated code.

Here's the way I did it: (using restify.js, but should work for express.js, or node itself too)

http://qugstart.com/blog/node-js/node-js-restify-server-with-both-http-and-https/

·深蓝 2024-12-11 21:57:48

更新了杰克答案的代码。与您的 https 服务器一起运行。

// set up plain http server
var express = require('express');
var app = express();
var http = require('http');

var server = http.createServer(app);

// set up a route to redirect http to https
app.get('*', function(req, res) {
  res.redirect('https://' + req.headers.host + req.url);
})

// have it listen on 80
server.listen(80);

Updated code for jake's answer. Run this alongside your https server.

// set up plain http server
var express = require('express');
var app = express();
var http = require('http');

var server = http.createServer(app);

// set up a route to redirect http to https
app.get('*', function(req, res) {
  res.redirect('https://' + req.headers.host + req.url);
})

// have it listen on 80
server.listen(80);
書生途 2024-12-11 21:57:48

这对我来说适用于 Express:

app.get("*",(req,res,next) => {
    if (req.headers["x-forwarded-proto"]) {
        res.redirect("https://" + req.headers.host + req.url)
    }
    if (!res.headersSent) {
        next()
    }
})

将其放在所有 HTTP 处理程序之前。

This works with express for me:

app.get("*",(req,res,next) => {
    if (req.headers["x-forwarded-proto"]) {
        res.redirect("https://" + req.headers.host + req.url)
    }
    if (!res.headersSent) {
        next()
    }
})

Put this before all HTTP handlers.

你的背包 2024-12-11 21:57:48

该脚本在加载页面时保存 URL 页面并检查该地址是 https 还是 http。如果是http,脚本会自动将您重定向到相同的https页面

(function(){
  var link = window.location.href;
  if(link[4] != "s"){
    var clink = "";
    for (let i = 4; i < link.length; i++) {
      clink += link[i];
    }
    window.location.href = "https" + clink;
  }
})();

This script while loading the page saves the URL page and checks if the address is https or http. If it is http, the script automatically redirects you to the same https page

(function(){
  var link = window.location.href;
  if(link[4] != "s"){
    var clink = "";
    for (let i = 4; i < link.length; i++) {
      clink += link[i];
    }
    window.location.href = "https" + clink;
  }
})();
兲鉂ぱ嘚淚 2024-12-11 21:57:48

这对我有用:

/* Headers */
require('./security/Headers/HeadersOptions').Headers(app);

/* Server */
const ssl = {
    key: fs.readFileSync('security/ssl/cert.key'),
    cert: fs.readFileSync('security/ssl/cert.pem')
};
//https server
https.createServer(ssl, app).listen(443, '192.168.1.2' && 443, '127.0.0.1');
//http server
app.listen(80, '192.168.1.2' && 80, '127.0.0.1');
app.use(function(req, res, next) {
    if(req.secure){
        next();
    }else{
        res.redirect('https://' + req.headers.host + req.url);
    }
});

建议在重定向到 https 之前添加标头

现在,当您这样做时:

curl http://127.0.0.1 --include

您会得到:

HTTP/1.1 302 Found
//
Location: https://127.0.0.1/
Vary: Accept
Content-Type: text/plain; charset=utf-8
Content-Length: 40
Date: Thu, 04 Jul 2019 09:57:34 GMT
Connection: keep-alive

Found. Redirecting to https://127.0.0.1/

我使用express 4.17.1

This worked for me:

/* Headers */
require('./security/Headers/HeadersOptions').Headers(app);

/* Server */
const ssl = {
    key: fs.readFileSync('security/ssl/cert.key'),
    cert: fs.readFileSync('security/ssl/cert.pem')
};
//https server
https.createServer(ssl, app).listen(443, '192.168.1.2' && 443, '127.0.0.1');
//http server
app.listen(80, '192.168.1.2' && 80, '127.0.0.1');
app.use(function(req, res, next) {
    if(req.secure){
        next();
    }else{
        res.redirect('https://' + req.headers.host + req.url);
    }
});

Recommend add the headers before redirect to https

Now, when you do:

curl http://127.0.0.1 --include

You get:

HTTP/1.1 302 Found
//
Location: https://127.0.0.1/
Vary: Accept
Content-Type: text/plain; charset=utf-8
Content-Length: 40
Date: Thu, 04 Jul 2019 09:57:34 GMT
Connection: keep-alive

Found. Redirecting to https://127.0.0.1/

I use express 4.17.1

初心未许 2024-12-11 21:57:48

这个想法是检查传入请求是否是通过 https 发出的,如果是,则只需不要再次将其重定向到 https,而是照常继续。否则,如果是 http,则通过附加 https 进行重定向。

app.use (function (req, res, next) {
  if (req.secure) {
          next();
  } else {
          res.redirect('https://' + req.headers.host + req.url);
  }
});

The idea is to check if the incoming request is made with https, if so simply don't redirect it again to https but continue as usual. Else, if it is http, redirect it with appending https.

app.use (function (req, res, next) {
  if (req.secure) {
          next();
  } else {
          res.redirect('https://' + req.headers.host + req.url);
  }
});
烙印 2024-12-11 21:57:48

经过多年对从 http 到 https 的完美重定向的研究,我在这里找到了完美的解决方案。

const http = require("http");
const https = require("https");

const { parse } = require("url");
const next = require("next");
const fs = require("fs");

const ports = {
http: 3000,
https: 3001
}

const dev = process.env.NODE_ENV !== "production";
const app = next({ dev });
const handle = app.getRequestHandler();

const httpsOptions = {
key: fs.readFileSync("resources/certificates/localhost-key.pem"),
cert: fs.readFileSync("resources/certificates/localhost.pem")
};

// Automatic HTTPS connection/redirect with node.js/express
// source: https://stackoverflow.com/questions/7450940/automatic-https- 
connection-redirect-with-node-js-express
app.prepare().then(() => {

// Redirect from http port to https
http.createServer(function (req, res) {
    res.writeHead(301, { "Location": "https://" + req.headers['host'].replace(ports.http, ports.https) + req.url });
    console.log("http request, will go to >> ");
    console.log("https://" + req.headers['host'].replace(ports.http, ports.https) + req.url);
    res.end();
}).listen(ports.http, (err) => {
    if (err) throw err;
    console.log("ready - started server on url: http://localhost:" + ports.http);
});

https.createServer(httpsOptions, (req, res) => {
    const parsedUrl = parse(req.url, true);
    handle(req, res, parsedUrl);
}).listen(ports.https, (err) => {
    if (err) throw err;
    console.log("ready - started server on url: https://localhost:" + ports.https);
});
});

From the long years of reseaching for a perfect redirection from http to https, I've found the perfect solution here.

const http = require("http");
const https = require("https");

const { parse } = require("url");
const next = require("next");
const fs = require("fs");

const ports = {
http: 3000,
https: 3001
}

const dev = process.env.NODE_ENV !== "production";
const app = next({ dev });
const handle = app.getRequestHandler();

const httpsOptions = {
key: fs.readFileSync("resources/certificates/localhost-key.pem"),
cert: fs.readFileSync("resources/certificates/localhost.pem")
};

// Automatic HTTPS connection/redirect with node.js/express
// source: https://stackoverflow.com/questions/7450940/automatic-https- 
connection-redirect-with-node-js-express
app.prepare().then(() => {

// Redirect from http port to https
http.createServer(function (req, res) {
    res.writeHead(301, { "Location": "https://" + req.headers['host'].replace(ports.http, ports.https) + req.url });
    console.log("http request, will go to >> ");
    console.log("https://" + req.headers['host'].replace(ports.http, ports.https) + req.url);
    res.end();
}).listen(ports.http, (err) => {
    if (err) throw err;
    console.log("ready - started server on url: http://localhost:" + ports.http);
});

https.createServer(httpsOptions, (req, res) => {
    const parsedUrl = parse(req.url, true);
    handle(req, res, parsedUrl);
}).listen(ports.https, (err) => {
    if (err) throw err;
    console.log("ready - started server on url: https://localhost:" + ports.https);
});
});
﹎☆浅夏丿初晴 2024-12-11 21:57:48

我的情况我还必须更改端口并监听两个端口:

appr.get("/", (req, res) => {
  res.redirect('https://' + req.headers['host'].replace(PORT, PORTS) + req.url);
});

My case i must change also the port and listen both ports:

appr.get("/", (req, res) => {
  res.redirect('https://' + req.headers['host'].replace(PORT, PORTS) + req.url);
});
谢绝鈎搭 2024-12-11 21:57:48

如果您的节点应用程序安装在 IIS 上,您可以在 web.config 中执行以下操作

<configuration>
    <system.webServer>

        <!-- indicates that the hello.js file is a node.js application 
    to be handled by the iisnode module -->

        <handlers>
            <add name="iisnode" path="src/index.js" verb="*" modules="iisnode" />
        </handlers>

        <!-- use URL rewriting to redirect the entire branch of the URL namespace
    to hello.js node.js application; for example, the following URLs will 
    all be handled by hello.js:
    
        http://localhost/node/express/myapp/foo
        http://localhost/node/express/myapp/bar
        -->
        <rewrite>
            <rules>
                <rule name="HTTPS force" enabled="true" stopProcessing="true">
                    <match url="(.*)" />
                    <conditions>
                        <add input="{HTTPS}" pattern="^OFF$" />
                    </conditions>
                    <action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" redirectType="Permanent" />
                </rule>
                <rule name="sendToNode">
                    <match url="/*" />
                    <action type="Rewrite" url="src/index.js" />
                </rule>
            </rules>
        </rewrite>

        <security>
            <requestFiltering>
                <hiddenSegments>
                    <add segment="node_modules" />
                </hiddenSegments>
            </requestFiltering>
        </security>

    </system.webServer>
</configuration>

if your node application install on IIS you can do like this in web.config

<configuration>
    <system.webServer>

        <!-- indicates that the hello.js file is a node.js application 
    to be handled by the iisnode module -->

        <handlers>
            <add name="iisnode" path="src/index.js" verb="*" modules="iisnode" />
        </handlers>

        <!-- use URL rewriting to redirect the entire branch of the URL namespace
    to hello.js node.js application; for example, the following URLs will 
    all be handled by hello.js:
    
        http://localhost/node/express/myapp/foo
        http://localhost/node/express/myapp/bar
        -->
        <rewrite>
            <rules>
                <rule name="HTTPS force" enabled="true" stopProcessing="true">
                    <match url="(.*)" />
                    <conditions>
                        <add input="{HTTPS}" pattern="^OFF
quot; />
                    </conditions>
                    <action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" redirectType="Permanent" />
                </rule>
                <rule name="sendToNode">
                    <match url="/*" />
                    <action type="Rewrite" url="src/index.js" />
                </rule>
            </rules>
        </rewrite>

        <security>
            <requestFiltering>
                <hiddenSegments>
                    <add segment="node_modules" />
                </hiddenSegments>
            </requestFiltering>
        </security>

    </system.webServer>
</configuration>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文