web-dev-qa-db-ja.com

Heroku NodeJS httpからhttps ssl強制リダイレクト

私は、https、を使用したエクスプレスノードでherokuでアプリケーションを実行しています。 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);
99

答えは、Herokuがプロキシのことであるように転送する「x-forwarded-proto」のヘッダーを使用することです。 (補足:便利な他のx-変数もいくつか渡します チェックアウト )。

私のコード:

/* 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 */
})

ブランドンのおかげで、自分の質問に答えられない6時間の遅延を待っていました。

93

本日現在、2014年10月10日Heroku Cedarスタック、およびExpressJS〜3.4.4を使用して、ここにコードのワーキングセットがあります。

ここで覚えておくべき主なことは、Herokuにデプロイしていることです。 SSL終了は、暗号化されたトラフィックがノードアプリに到達する前に、ロードバランサーで発生します。 req.headers ['x-forwarded-proto'] === 'https'を使用して、httpsを使用して要求を行うかどうかをテストできます。

他の環境でホストしている場合のように、アプリ内などでローカルSSL証明書を保持することに心配する必要はありません。ただし、独自の証明書、サブドメインなどを使用する場合は、最初にHerokuアドオンを介してSSLアドオンを適用する必要があります。

次に、以下を追加して、HTTPS以外からHTTPSへのリダイレクトを実行します。これは上記の受け入れられた答えに非常に近いですが、:

  1. 「app.use」を使用するようにします(getだけでなく、すべてのアクションに対して)
  2. ForceSslロジックを宣言された関数に明示的に外部化します
  3. 「app.use」で「*」を使用しません-実際にテストすると失敗しました。
  4. ここでは、実稼働環境でのみ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']

103
arcseldon

受け入れられた回答にはハードコードされたドメインがあります。これは、複数のドメインに同じコードがある場合はあまり良くありません(例: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/

21

ExpressプロジェクトでSSLを実施する小さなノードモジュールを作成しました。標準的な状況とリバースプロキシ(Heroku、nodejitsuなど)の両方で機能します。

https://github.com/florianheinemann/express-sslify

16
florian

Localhostのx-forwarded-protoヘッダーをテストする場合は、 nginx を使用して仮想ホストをセットアップできます。ノードアプリへのすべてのリクエストをプロキシするファイル。 nginx vhost設定ファイルは次のようになります

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

ここで重要なことは、すべてのリクエストを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
6
simo

Cloudflare.comをherokuと組み合わせてCDNとして使用している場合、次のようにcloudflare内で自動SSLリダイレクトを簡単に有効にできます。

  1. ログインしてダッシュボードに移動します

  2. ページルールを選択

    Select Page Rules

  3. ドメインを追加します(例: www.example.comおよびスイッチは常にhttpsをオンに使用します Switch always use https to on
4
Ben Marten

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

ループバックユーザーは、ミドルウェアとしてarcseldon answerのわずかに適合したバージョンを使用できます。

server/middleware/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

var forceSSL = require('./middleware/forcessl.js');
app.use(forceSSL());
3
Bunker

これを行うための、より明確な具体的な方法。

  app.enable('trust proxy');
  app.use('*', (req, res, next) => {
    if (req.secure) {
      return next();
    }
    res.redirect(`https://${req.hostname}${req.url}`);
  });
1
denixtry

X-Forwarded-Protoヘッダーのプロトコルをチェックすることは、Derekが指摘したように、Herokuでも問題なく機能します。それが価値があるものについては、 ここに要点 私が使用するExpressミドルウェアとそれに対応するテストの。

0
Peter Marklund
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 */
  }
});
0
Chiedo