你如何强制在Azure网站上的node.js上表达使用https?

时间:2013-12-14 00:28:11

标签: node.js ssl https express azure-web-sites

在Windows Azure网站上运行,我想通过默认的* .azurewebsites.net证书使用ssl。它无需任何操作,但http也可用于每个目的地,而不仅仅是https。如何强制从http重定向到https?通常我可以做类似的事情:

var https = require('https');

...

var options = {
      key: fs.readFileSync('path.key'),
      cert: fs.readFileSync('path.crt')
    };

...

https.createServer(options, app)

但是因为我对* .azurewebsites.net证书一无所知,例如它的路径,所以它不起作用。

如何将所有或部分请求重定向到https?

4 个答案:

答案 0 :(得分:6)

web.config中,在具有stopProcessing="true"的任何其他规则之前添加以下规则。

<rule name="RedirecttoHTTPS">
  <match url="(.*)" />
  <conditions>
    <add input="{HTTPS}" pattern="off" ignoreCase="true" />
    <add input="{URL}" pattern="/$" negate="true" />
    <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
  </conditions>
  <action type="Redirect" url="https://{SERVER_NAME}/{R:1}" redirectType="SeeOther" />
</rule>

如果您想使用* .azurewebsite.net通配符证书,也可以使用普通http.createServer(app)进行生产。

参考文献:

  1. How to require SSL in IIS7 and Azure with Rewrite
  2. URL Rewrite Module Configuration Reference

答案 1 :(得分:5)

接受的答案对我不起作用,它只显示一个空白页面,这个:

<!-- Redirect all traffic to SSL -->
    <rule name="Force HTTPS" enabled="true">
      <match url="(.*)" ignoreCase="false" />
      <conditions>
        <add input="{HTTPS}" pattern="off" />
      </conditions>
      <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" appendQueryString="true" redirectType="Permanent" />
    </rule>

https://gist.github.com/tstpierre/afec7eb409aebe0bf3d1完美无缺。

答案 2 :(得分:1)

如果您希望验证节点应用是否从节点应用中获得安全流量,那么Richard Astbury会有solution on his blog

tl; dr :IIS充当节点应用的代理,并为请求添加“x-arr-ssl”标头,如果它们是通过HTTPS提供的。您还可以使用“x-site-deployment-id”标头来验证您的应用当前是否在azure中运行。中间件最终如此:

function requireHTTPS(req, res, next) {
    var isAzure = req.get('x-site-deployment-id'),
        isSsl = req.get('x-arr-ssl');

    if (isAzure && !isSsl) {
        return res.redirect('https://' + req.get('host') + req.url);
    }

    next();
}

app.use(requireHTTPS);

当你在这里时,最好也加入HSTS:

var helmet = require('helmet');

function requireHTTPS(req, res, next) {
    var isAzure = req.get('x-site-deployment-id'),
        isSsl = req.get('x-arr-ssl');

    if (isAzure && !isSsl) {
        return res.redirect('https://' + req.get('host') + req.url);
    }

    next();
}

app.use(requireHTTPS);
app.use(helmet.hsts({
    maxAge: 10886400000,     // Must be at least 18 weeks to be approved by Google
    includeSubdomains: true, // Must be enabled to be approved by Google
    preload: true
}));

当然,您可以随时与web.config回答一起执行此操作。

答案 3 :(得分:0)

由于听起来Azure网站在您的案例中充当反向代理,这个approch可能适合您:

如果您可以从以下方面获得协议,它应该可以帮助您:

req.headers['x-forwarded-proto']

如果它对您所服务的资源无效,则应该为您提供您需要按键的http或https以进行重定向。

我在下次获取请求时使用以下代码重定向(例如,对于html文件或站点根目录)。我将我想要的所有文件都安全地放在/ secure目录中,以便更容易知道ssl应该和不应该是什么:

protocol = req.headers['x-forwarded-proto'];

if ((req.url.lastIndexOf('.html') == (req.url.length - 5)) || (req.url.slice(-1) == '/')) {
    if (protocol == 'http') {

        if (req.url.indexOf('/secure/') == 0) {
            console.log('Non ssl request made to secure resource: ' + req.url);
            console.log('Redirecting to https://' + site_host_name + req.url);
            res.writeHead(301,
                {Location: 'https://' + site_host_name + req.url}
            );
            res.end();
            return;
        } else {
            next();
            return;
        }
    } else {
        if (req.url.indexOf('/secure/') != 0) {
            console.log('ssl request made for non-secure resource: ' + req.url);
            console.log('Redirecting to http://' + site_host_name + req.url);
            res.writeHead(301,
                {Location: 'http://' + site_host_name + req.url}
            );
            res.end();
            return;
        } else {
            next();
            return;
        }
    }
}