使用 node.js/express 自动 HTTPS 连接/重定向
我一直在尝试使用我正在开发的 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(23)
瑞安,谢谢你为我指明了正确的方向。我用一些代码充实了你的答案(第二段),它有效。在这种情况下,这些代码片段被放入我的express应用程序中:
https express服务器在3000上侦听ATM。我设置了这些iptables规则,以便节点不必以root身份运行:
总之,这完全按照我想要的方式工作到。
要防止通过 HTTP 窃取 Cookie,请参阅此答案< /a> (来自注释)或使用以下代码:
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:
The https express server listens ATM on 3000. I set up these iptables rules so that node doesn't have to run as root:
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:
感谢这个人:
https://www.tonyerwin.com/2014 /09/redirecting-http-to-https-with-nodejs.html
如果安全,则通过 https 请求,否则重定向到 https
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
如果您遵循传统端口,因为 HTTP 默认情况下尝试端口 80,HTTPS 默认情况下尝试端口 443,您可以在同一台计算机上简单地拥有两个服务器:
代码如下:
使用 https 进行测试:
使用 http:
更多详细信息: 通过同一端口的 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:
Test with https:
With http:
More details : Nodejs HTTP and HTTPS over same port
使用 Nginx,您可以利用“x-forwarded-proto”标头:
With Nginx you can take advantage of the "x-forwarded-proto" header:
从 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.
我使用 Basarat 提出的解决方案,但我还需要覆盖端口,因为我曾经有 2 个不同的 HTTP 和 HTTPS 协议端口。
我也更喜欢使用非标准端口,这样就可以在没有root权限的情况下启动nodejs。
我喜欢 8080 和 8443,因为我有多年的 tomcat 编程经验。
我的完整文件变成
然后我使用 iptable 在我的 HTTP 和 HTTPS 端口上转发 80 和 443 流量。
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.
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
Then I use iptable for forwording 80 and 443 traffic on my HTTP and HTTPS ports.
您可以使用 express-force-https 模块:
npm install - -保存express-force-https
You can use the express-force-https module:
npm install --save express-force-https
我发现 req.protocol 在我使用express时有效(没有测试过,但我怀疑它有效)。使用当前节点 0.10.22 和 Express 3.4.3
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
该答案需要更新才能与 Express 4.0 一起使用。以下是我如何让单独的 http 服务器工作:
This answer needs to be updated to work with Express 4.0. Here is how I got the separate http server to work:
如果您的应用程序位于受信任的代理(例如 AWS ELB 或正确配置的 nginx)后面,则此代码应该可以工作:
注意:
If your app is behind a trusted proxy (e.g. an AWS ELB or a correctly configured nginx), this code should work:
Notes:
这里的大多数答案建议使用 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.
你可以使用“net”模块来监听HTTP和HTTP协议。同一端口上的 HTTPS
you can use "net" module to listening for HTTP & HTTPS on the same port
这就是我们使用的并且效果很好!
This is what we use and it works great!
这对我有用:
This worked for me:
您可以实例化 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/
更新了杰克答案的代码。与您的 https 服务器一起运行。
Updated code for jake's answer. Run this alongside your https server.
这对我来说适用于 Express:
将其放在所有 HTTP 处理程序之前。
This works with express for me:
Put this before all HTTP handlers.
该脚本在加载页面时保存 URL 页面并检查该地址是 https 还是 http。如果是http,脚本会自动将您重定向到相同的https页面
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
这对我有用:
建议在重定向到 https 之前添加标头
现在,当您这样做时:
您会得到:
我使用express 4.17.1
This worked for me:
Recommend add the headers before redirect to https
Now, when you do:
You get:
I use express 4.17.1
这个想法是检查传入请求是否是通过 https 发出的,如果是,则只需不要再次将其重定向到 https,而是照常继续。否则,如果是 http,则通过附加 https 进行重定向。
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.
经过多年对从 http 到 https 的完美重定向的研究,我在这里找到了完美的解决方案。
From the long years of reseaching for a perfect redirection from http to https, I've found the perfect solution here.
我的情况我还必须更改端口并监听两个端口:
My case i must change also the port and listen both ports:
如果您的节点应用程序安装在 IIS 上,您可以在 web.config 中执行以下操作
if your node application install on IIS you can do like this in web.config