在Express / Node中强制通过https请求

时间:2012-03-15 11:54:36

标签: node.js express

我有一个在端口3100上运行的Express.js(v 2.5.8)(节点v0.6.12)服务器。它由Nginx前端,它将http和https请求代理到端口3100.

我想通过https强制某些网址。这是一个例子(app是我的Express服务器):

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);
    }
}

重定向有效,但节点(超时后)会抛出错误,说“无法获取/应用现在

重定向到ssl的正确方法是什么?

7 个答案:

答案 0 :(得分:6)

据我所知,您正在使用nginx协商SSL并将http和https请求代理到您的Express应用程序。如果可能的话,我会选择在nginx中解决这个问题,但如果nginx无法知道哪些路径应该受到保护(即只能通过https获得),或者你想在快递应用中出于其他原因这样做,这里有一些信息:

您应该从nginx获取X-Forwarded-Proto,仅在原始协议为https时设置为https。以下是在nginx中执行此操作的方法:

proxy_set_header X-Forwarded-Proto https;

我还会转发Host标题:

proxy_set_header Host $http_host;

在您的快递应用中,检查一下,或者在标题和请求的路径中重定向到主机(快递解析到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);
    }
}

答案 1 :(得分:0)

您需要2个不同的快速app对象才能执行此操作。快速服务器的每个实例一次只能侦听一个协议。这可以都在一个node.js进程中,但是您需要2个不同配置的快速服务器app实例,一个用于http,另一个用于https。请参阅我的答案以获取示例:

How to force SSL / https in Express.js

另请参阅:Automatic HTTPS connection/redirect with node.js/express

另请注意,您不应指定req.session.ssl。将其设置为true并不会神奇地使客户端与TLS而不是明文HTTP连接。这是一个只读属性。分配它没有效果。

您还应注意,您无法在单个端口上同时运行http和https。这就是为什么http使用80而https使用443。

当您收到Cannot GET /applyNow错误时,这意味着您的快速路由从未与请求路径匹配,因此您的ensureSec中间件从未被调用过。

答案 2 :(得分:0)

您可以在nginx服务器上配置ssl端口,并像其他请求一样代理对node.js的请求。

http://nginx.org/en/docs/http/configuring_https_servers.html

无需更改node.js应用。只需使用您的证书和对node.js app的代理请求在nginx上配置443端口。

答案 3 :(得分:0)

要添加Peter Lyons所说的内容,请明确要求您在端口上只运行一台服务器。如果您尝试在一个端口上运行两个http服务器,它将抛出EADDRINUSE错误。

答案 4 :(得分:0)

如下所述: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);  
});

答案 5 :(得分:0)

当您在前端使用Nginx时,实现此目的的最简洁和最简单的方法是将Nginx中的http URL转发(重写)为HTTPS,而不是尝试在Express中重定向。这可以按如下方式完成:

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所需的路线或规则相匹配。

答案 6 :(得分:0)

app.enable(' trust proxy');

"在Varnish或Nginx等反向代理后面使用Express是微不足道的,但它确实需要配置。通过启用"信任代理"通过app.enable设置('信任代理'),Express会知道它位于代理后面,并且X-Forwarded- *标题字段可能是可信的,否则可能很容易。欺骗"

Express behind proxies doco