Heroku NodeJS http 到 https ssl 强制重定向
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7185074/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Heroku NodeJS http to https ssl forced redirect
提问by Derek Bredensteiner
I have an application up and running on heroku with express on node with https,. How do I identify the protocol to force a redirect to https with nodejs on heroku?
我有一个应用程序在 heroku 上启动并运行,并在节点上使用 https,快速运行。如何在heroku上使用nodejs确定强制重定向到https的协议?
My app is just a simple http server, it doesn't (yet) realize heroku is sending it https requests:
我的应用程序只是一个简单的 http 服务器,它(还)没有意识到 heroku 正在向它发送 https 请求:
/* Heroku provides the port they want you on in this environment variable (hint: it's not 80) */
app.listen(process.env.PORT || 3000);
采纳答案by Derek Bredensteiner
The answer is to use the header of 'x-forwarded-proto' that Heroku passes forward as it does it's proxy thingamabob. (side note: They pass several other x- variables too that may be handy, check them out).
答案是使用 Heroku 传递的“x-forwarded-proto”的标头,因为它是代理 thingamabob。(旁注:他们也传递了其他几个可能很方便的 x 变量,请查看它们)。
My code:
我的代码:
/* At the top, with other redirect methods before other routes */
app.get('*',function(req,res,next){
if(req.headers['x-forwarded-proto']!='https')
res.redirect('https://mypreferreddomain.com'+req.url)
else
next() /* Continue to other routes if we're not redirecting */
})
Thanks Brandon, was just waiting for that 6 hour delay thing that wouldn't let me answer my own question.
谢谢布兰登,只是在等待 6 小时的延迟,这不会让我回答我自己的问题。
回答by arcseldon
As of today, 10th October 2014, using Heroku Cedar stack, and ExpressJS ~3.4.4, here is a working set of code.
截至今天,2014 年 10 月 10 日,使用Heroku Cedar stack和ExpressJS ~3.4.4,这里是一组工作代码。
The main thing to remember here is that we ARE deploying to Heroku. SSL termination happens at the load balancer, before encrypted traffic reaches your node app. It is possible to test whether https was used to make the request with req.headers['x-forwarded-proto'] === 'https'.
这里要记住的主要事情是我们正在部署到 Heroku。在加密流量到达您的节点应用程序之前,SSL 终止发生在负载均衡器上。可以使用req.headers['x-forwarded-proto'] === 'https'来测试 https 是否用于发出请求。
We don't need to concern ourselves with having local SSL certificates inside the app etc as you might if hosting in other environments. However, you should get a SSL Add-On applied via Heroku Add-ons first if using your own certificate, sub-domains etc.
我们不需要像在其他环境中托管一样担心在应用程序中拥有本地 SSL 证书等。但是,如果使用您自己的证书、子域等,您应该首先通过 Heroku 附加组件应用 SSL 附加组件。
Then just add the following to do the redirect from anything other than HTTPS to HTTPS. This is very close to the accepted answer above, but:
然后只需添加以下内容即可从 HTTPS 以外的任何内容重定向到 HTTPS。这非常接近上面接受的答案,但是:
- Ensures you use "app.use" (for all actions, not just get)
- Explicitly externalises the forceSsl logic into a declared function
- Does not use '*' with "app.use" - this actually failed when I tested it.
- Here, I only want SSL in production. (Change as suits your needs)
- 确保您使用“app.use”(用于所有操作,而不仅仅是获取)
- 将 forceSsl 逻辑显式外部化为声明的函数
- 不将 '*' 与“app.use”一起使用 - 当我测试它时,这实际上失败了。
- 在这里,我只希望在生产中使用 SSL。(根据您的需要更改)
Code:
代码:
var express = require('express'),
env = process.env.NODE_ENV || 'development';
var forceSsl = function (req, res, next) {
if (req.headers['x-forwarded-proto'] !== 'https') {
return res.redirect(['https://', req.get('Host'), req.url].join(''));
}
return next();
};
app.configure(function () {
if (env === 'production') {
app.use(forceSsl);
}
// other configurations etc for express go here...
}
Note for SailsJS (0.10.x) users. You can simply create a policy (enforceSsl.js) inside api/policies:
SailsJS (0.10.x) 用户注意事项。您可以简单地在 api/policies 中创建一个策略 (enforceSsl.js):
module.exports = function (req, res, next) {
'use strict';
if ((req.headers['x-forwarded-proto'] !== 'https') && (process.env.NODE_ENV === 'production')) {
return res.redirect([
'https://',
req.get('Host'),
req.url
].join(''));
} else {
next();
}
};
Then reference from config/policies.js along with any other policies, e.g:
然后从 config/policies.js 以及任何其他策略中引用,例如:
'*': ['authenticated', 'enforceSsl']
'*': ['已认证', 'enforceSsl']
回答by Joan-Diego Rodriguez
The accepted answer has a hardcoded domain in it, which isn't too good if you have the same code on several domains (eg: dev-yourapp.com, test-yourapp.com, yourapp.com).
接受的答案中有一个硬编码的域,如果您在多个域(例如:dev-yourapp.com、test-yourapp.com、yourapp.com)上有相同的代码,这不是太好。
Use this instead:
改用这个:
/* Redirect http to https */
app.get('*', function(req,res,next) {
if(req.headers['x-forwarded-proto'] != 'https' && process.env.NODE_ENV === 'production')
res.redirect('https://'+req.hostname+req.url)
else
next() /* Continue to other routes if we're not redirecting */
});
https://blog.mako.ai/2016/03/30/redirect-http-to-https-on-heroku-and-node-generally/
https://blog.mako.ai/2016/03/30/redirect-http-to-https-on-heroku-and-node-generally/
回答by florian
I've written a small node module that enforces SSL on express projects. It works both in standard situations and in case of reverse proxies (Heroku, nodejitsu, etc.)
我编写了一个小节点模块,用于在 express 项目上强制执行 SSL。它既适用于标准情况,也适用于反向代理(Heroku、nodejitsu 等)
回答by simo
If you want to test out the x-forwarded-protoheader on your localhost, you can use nginxto setup a vhost file that proxies all of the requests to your node app. Your nginx vhost config file might look like this
如果您想测试x-forwarded-proto本地主机上的标头,您可以使用nginx设置一个 vhost 文件,该文件将所有请求代理到您的节点应用程序。您的 nginx vhost 配置文件可能如下所示
NginX
nginx
server {
listen 80;
listen 443;
server_name dummy.com;
ssl on;
ssl_certificate /absolute/path/to/public.pem;
ssl_certificate_key /absolute/path/to/private.pem;
access_log /var/log/nginx/dummy-access.log;
error_log /var/log/nginx/dummy-error.log debug;
# node
location / {
proxy_pass http://127.0.0.1:3000/;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
The important bits here are that you are proxying all requests to localhost port 3000 (this is where your node app is running) and you are setting up a bunch of headers including X-Forwarded-Proto
这里的重要部分是您将所有请求代理到本地主机端口 3000(这是您的节点应用程序运行的位置),并且您正在设置一堆标头,包括 X-Forwarded-Proto
Then in your app detect that header as usual
然后在您的应用程序中像往常一样检测该标题
Express
表达
var app = express()
.use(function (req, res, next) {
if (req.header('x-forwarded-proto') == 'http') {
res.redirect(301, 'https://' + 'dummy.com' + req.url)
return
}
next()
})
Koa
考阿
var app = koa()
app.use(function* (next) {
if (this.request.headers['x-forwarded-proto'] == 'http') {
this.response.redirect('https://' + 'dummy.com' + this.request.url)
return
}
yield next
})
Hosts
主机
Finally you have to add this line to your hostsfile
最后,您必须将此行添加到您的hosts文件中
127.0.0.1 dummy.com
回答by Julien Le Coupanec
You should take a look at heroku-ssl-redirect. It works like a charm!
你应该看看heroku-ssl-redirect。它就像一个魅力!
var sslRedirect = require('heroku-ssl-redirect');
var express = require('express');
var app = express();
// enable ssl redirect
app.use(sslRedirect());
app.get('/', function(req, res){
res.send('hello world');
});
app.listen(3000);
回答by electronix384128
If you are using cloudflare.com as CDN in combination with heroku, you can enable automatic ssl redirect within cloudflare easily like this:
如果您将 cloudflare.com 作为 CDN 与 heroku 结合使用,您可以像这样轻松地在 cloudflare 中启用自动 ssl 重定向:
Login and go to your dashboard
Select Page Rules

- Add your domain, e.g. www.example.com and switch always use https to on

登录并转到您的仪表板
选择页面规则

- 添加您的域,例如 www.example.com 并将始终使用 https 切换为 on

回答by Bunker
Loopback users can use a slightly adapted version of arcseldon answer as middleware:
Loopback 用户可以使用稍微修改过的 arcseldon answer 作为中间件:
server/middleware/forcessl.js
服务器/中间件/forcessl.js
module.exports = function() {??
return function forceSSL(req, res, next) {
var FORCE_HTTPS = process.env.FORCE_HTTPS || false;
if (req.headers['x-forwarded-proto'] !== 'https' && FORCE_HTTPS) {
return res.redirect(['https://', req.get('Host'), req.url].join(''));
}
next();
};
};
server/server.js
服务器/server.js
var forceSSL = require('./middleware/forcessl.js');
app.use(forceSSL());
回答by denixtry
This is a more Express specific way to do this.
这是执行此操作的更 Express 特定的方法。
app.enable('trust proxy');
app.use('*', (req, res, next) => {
if (req.secure) {
return next();
}
res.redirect(`https://${req.hostname}${req.url}`);
});
回答by tuancharlie
With app.use and dynamic url. Works both localy and on Heroku for me
使用 app.use 和动态 url。对我来说在本地和 Heroku 上都有效
app.use(function (req, res, next) {
if (req.header('x-forwarded-proto') === 'http') {
res.redirect(301, 'https://' + req.hostname + req.url);
return
}
next()
});

