在Express / Node中通过https强制请求
我在端口3100上运行了一个Express.js(v 2.5.8)(节点v0.6.12)服务器。它由Nginx前端实现,它将http和https请求代理到端口3100。
我想通过https强制某些url。 这是一个例子(应用程序是我的快递服务器):
app.get('/applyNow', ensureSec, secure.showApplication );
ensureSec是我试图用来检查连接是否通过SSL的函数:
function ensureSec(req, res, next) { if (req.session.ssl == true) { return next(); } else { req.session.ssl = true; res.redirect('https://' + url.parse(req.headers.referer).host + url.parse(req.url).pathname); } }
redirect工作,但节点(超时后)抛出一个错误说:不能GET / applyNow
什么是redirect到ssl的正确方法?
据我所知,你正在使用nginx协商SSL和代理的http和https请求到您的快递应用程序。 如果可能的话,我会select在nginx中解决这个问题,但是如果nginx无法知道哪些path应该受到保护(即只能通过https访问),或者您想在快速应用程序中执行此操作,信息:
您应该从nginx获得X-Forwarded-Proto
,仅在原始协议为https时才设置为https。 下面是你如何在nginx中做到这一点:
proxy_set_header X-Forwarded-Proto https;
我也会转发Host
头:
proxy_set_header Host $http_host;
在您的快速应用程序,检查,或在标题和请求的pathredirect到主机(快递parsing到req.path
所以你不必):
function ensureSec(req, res, next) { if (req.headers['x-forwarded-proto'] == 'https') { return next(); } else { res.redirect('https://' + req.headers.host + req.path); } }
您需要2个不同的快速app
对象来执行此操作 快速服务器的每个实例一次只能在一个协议上进行监听。 这可以全部在一个node.js过程中,但是您需要2个不同configuration的快速服务器app
实例,一个用于http,另一个用于https。 看到我的答案为例:
如何在Express.js中强制使用SSL / https
另请参阅: 自动HTTPS连接/使用node.js / expressredirect ?
还要注意,你不应该分配req.session.ssl
。 将其设置为true并不奇妙地使得客户端连接TLS而不是明文HTTP。 这是一个只读属性。 分配它没有效果。
您还应该注意,您不能在单个端口上运行http和https。 这就是为什么http使用80和https使用443。
当你得到Cannot GET /applyNow
错误,这意味着你的expresspath永远不匹配请求path,因此你的ensureSec
中间件从来没有被调用过。
您可以在您的nginx服务器上configurationssl端口,并像其他请求一样将请求代理到node.js。
http://nginx.org/en/docs/http/configuring_https_servers.html
无需更改node.js应用程序。 只需在nginx上configuration443端口,并将证书和代理请求发送到node.js应用程序。
为了补充Peter Lyons所说的话,明确规定你只能在一个端口上运行一台服务器。 如果你尝试在一个端口上运行两个http服务器,它会抛出一个EADDRINUSE错误。
正如在这里解释的: http : //elias.kg/post/14971446990/force-ssl-with-express-js-on-heroku-nginx ,与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); });
正如你在前端使用Nginx一样,最简单和最简单的方法是将Nginx中的http URLs转发(重写)为HTTPS,而不是尝试在Express中redirect。 这可以如下完成:
server { listen 12.34.56.78:80; server_name yourserver.com; location / { rewrite ^ https://$server_name$request_uri permanent; } }
你可以用这一行重写:
rewrite ^ https://ducklington.org$request_uri permanent;
只需设置您的位置,以匹配您需要转发到https的路线或规则。
app.enable('信任代理');
“在反向代理(如Varnish或Nginx)后面使用Express是微不足道的,但它确实需要configuration。通过通过app.enable('trust proxy')启用”trust proxy“设置,Express将知道它位于代理而X-Forwarded- *头域可能是可信的,否则可能很容易被欺骗。
表示在代理doco后面
- TypeError:对象#<ServerResponse>没有方法“发送”
- Sequelize updateAttributes在socket.on('disconnet')中不起作用
- 如何使用快递从服务器下载文件
- express express-parser中间件将数据放入属性名称中
- node.js与快递 – 显示自定义错误消息
- 如何处理asynchronous。 findOrCreate护照和mongoose的方法
- 如何完全删除一个nodejs模块的所有function,甚至包括setInterval?
- ExpressJS Promise和EventEmitter之间明显的竞争状态
- 玉和客户端的JavaScript