我在heroku上运行了一个应用程序,并使用https在节点上运行。如何识别协议以强制重定向到heroku上的nodejs进行https?
我的应用程序只是一个简单的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);
答案 0 :(得分:101)
截至今天, 2014年10月10日,使用 Heroku Cedar堆栈和 ExpressJS~3.4.4 ,这是一个工作集码。
这里要记住的主要事情是我们正在部署到Heroku。在加密流量到达您的节点应用之前,SSL终止发生在负载均衡器上。可以使用 req.headers [' x-forwarded-proto'] ===' https' 来测试https是否用于发出请求。
我们不需要关心在应用程序内部使用本地SSL证书,就像在其他环境中托管一样。但是,如果使用自己的证书,子域等,则应首先通过Heroku附加组件应用SSL加载项。
然后,只需添加以下内容即可从HTTPS以外的任何位置重定向到HTTPS。 这非常接近上面接受的答案,但是:
- 确保您使用" app.use" (对于所有行动,不仅仅是获取)
- 将forceSsl逻辑显式外部化为声明的函数
- 不使用' *'使用" app.use" - 当我这真的失败了 测试了它。
- 在这里,我只想在生产中使用SSL。 (根据您的需要改变)
醇>
代码:
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...
}
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();
}
};
然后从config / policies.js引用以及任何其他策略,例如:
' *':['经过身份验证',' enforceSsl']
答案 1 :(得分:93)
答案是使用Heroku传递的'x-forwarded-proto'的标题,因为它是代理的thingamabob。 (旁注:他们也传递了其他几个可能很方便的x变量,check them out)。
我的代码:
/* 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 */
})
感谢Brandon,只是等待那个让我回答自己问题的6小时延迟的事情。
答案 2 :(得分:21)
接受的答案中包含一个硬编码域,如果您在多个域上使用相同的代码(例如:dev-yourapp.com,test-yourapp.com,yourapp.com),则该域名不太好。
请改用:
/* 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/
答案 3 :(得分:16)
我编写了一个小型节点模块,可以对快速项目强制执行SSL。它既适用于标准情况,也适用于反向代理(Heroku,nodejitsu等)
答案 4 :(得分:6)
如果要在本地主机上测试x-forwarded-proto
标头,可以使用nginx设置代理节点应用程序所有请求的vhost文件。您的nginx vhost配置文件可能如下所示
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;
}
}
这里的重要部分是您将所有请求代理到localhost端口3000(这是您的节点应用程序正在运行的位置),并且您正在设置一堆标题,包括X-Forwarded-Proto
然后在您的应用中检测该标头
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()
})
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
文件
127.0.0.1 dummy.com
答案 5 :(得分:4)
如果您使用cloudflare.com作为CDN与heroku结合使用,您可以轻松地在cloudflare中启用自动ssl重定向:
登录并转到信息中心
选择页面规则
答案 6 :(得分:3)
Loopback用户可以使用稍微改编版的arcseldon answer作为中间件:
服务器/中间件/ 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.js
var forceSSL = require('./middleware/forcessl.js');
app.use(forceSSL());
答案 7 :(得分:2)
你应该看看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);
答案 8 :(得分:1)
我正在使用 Vue、Heroku 并且遇到了同样的问题:
我如下更新了我的 server.js,我不再碰它了,因为它正在工作:) :
const serveStatic = require('serve-static')
const sts = require('strict-transport-security');
const path = require('path')
var express = require("express");
require("dotenv").config();
var history = require("connect-history-api-fallback");
const app = express()
const globalSTS = sts.getSTS({'max-age':{'days': 365}});
app.use(globalSTS);
app.use(
history({
verbose: true
})
);
app.use((req, res, next) => {
if (req.header('x-forwarded-proto') !== 'https') {
res.redirect(`https://${req.header('host')}${req.url}`)
} else {
next();
}
});
app.use('/', serveStatic(path.join(__dirname, '/dist')));
app.get(/.*/, function (req, res) {
res.sendFile(path.join(__dirname, '/dist/index.html'))
})
const port = process.env.PORT || 8080
app.listen(port)
console.log(`app is listening on port: ${port}`)
答案 9 :(得分:0)
检查X-Forwarded-Proto标头中的协议在Heroku上运行正常,就像Derek指出的那样。对于它的价值,here is a gist我使用的Express中间件及其相应的测试。
答案 10 :(得分:0)
app.all('*',function(req,res,next){
if(req.headers['x-forwarded-proto']!='https') {
res.redirect(`https://${req.get('host')}`+req.url);
} else {
next(); /* Continue to other routes if we're not redirecting */
}
});
答案 11 :(得分:0)
更明确的具体方法。
app.enable('trust proxy');
app.use('*', (req, res, next) => {
if (req.secure) {
return next();
}
res.redirect(`https://${req.hostname}${req.url}`);
});
答案 12 :(得分:0)
带有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()
});