2016-08-09 16 views
3

私はNode/ExpressでバックエンドAPIを構築しています。これはMongoDBからデータを取得します。正面はReactで書かれます。ノード/エクスプレス - クライアント/サーバ間の安全な通信のための良いアプローチ

私は通信クライアント/サーバーを保護したいと思いますが、私はそのプロセスについてどう考えなければならないか分かりません。

passportまたはJWTに関するチュートリアルが多数ありますが、これはユーザー認証に適しています。

時間に基づいてリクエストごとにトークンを作成することは良いアプローチか、ウェブアプリケーションでは多すぎるかどうかはわかりません。

私の目標は、APIがプライベートであっても簡単にルートを見つけて、郵便配達でリクエストを偽ったり、データをスクラップする方法を見つけようとするためです。

+3

半関連のメモでは、HTTPSを有効にすることが最初のステップであると考えています([LetsEncrypt](https://letsencrypt.org/)から無料の証明書を取得できます)セッション認証メカニズムまた、XSS、CSRFなどの一般的な攻撃から保護するための[OWASP](https://www.owasp.org/index.php/Main_Page)サイトの情報をお読みください。 – mscdex

+0

ありがとう!私はXSSのような攻撃の束を既に扱っている「ヘルメット」というミドルウェアを有効にしています。 https://www.npmjs.com/package/helmet あなたのリンクを見ていきます。メルシ! 私は個人的なウェブサイトのためにそれを使用したので私は確かにHTTPSを使用し、LetsEncryptについて知っている(私は今思う)。しかし、私はまだdevモード(localhost)になっているので、実際のサーバがアップしたときにやっていきます。ありがとう。 – Ragnar

答えて

2

固定されたAPIキーを使用するのが標準です。この情報の平和は、ヘッダー内の各リクエストで送信するランダムに生成された文字列でなければなりません。サーバーがヘッダーにAPI KEYが存在するかどうかを確認するたびに、HTTP要求をチェックする必要があります。そうであれば、環境変数に格納されている値と照合する必要があります(コードにAPI KEYを格納しないでください)。

APIキーが侵害された場合は、env変数を簡単に更新することができます。

誰もがトラフィックを盗聴してAPIキーを見ることができるので、このソリューションはHTTPS接続なしで無意味になります。この場合、暗号化された接続が必須です。

このアプローチは、公開APIを持っている事実上すべての企業で使用されます。例えばTwitterやFacebook、Twilioは、Googleなど

Googleは、余分な彼らはあなたに失効するトークンを与えるステップが、これを持っていますあなたのケースでは、少なくとも初めには殺すでしょう。

次のコードは、あなたが全体の実装hearでファイル全体を確認することができます

app.use(function(req, res, next) { 

    // 
    // 1. Check if the APIKey is present 
    // 
    if(!req.headers.authorization) 
    { 
     return res.status(400).json(
      { 
       message: "Missing APIKey.", 
       description: "Unable to find the APIKey" 
      } 
     ); 
    } 

    // 
    // 2. Remove Basic from the beginning of the string 
    // 
    let noBasic = req.headers.authorization.replace('Basic ', ''); 

    // 
    // 3. Convert from base64 to string 
    // 
    let b64toString = new Buffer(noBasic, 'base64').toString("utf8"); 

    // 
    // 4. Remove the colon from the end of the string 
    // 
    let userAPIKey = b64toString.replace(':', ''); 

    // 
    // 5. Check if the APIKey matches the one on the server side. 
    // 
    if(userAPIKey != process.env.API_KEY) 
    { 
     return res.status(400).json(
      { 
       message: "APIKey don't match", 
       description: "Make sure what you are sending is what is in your server." 
      } 
     ); 
    } 

    // 
    // -> Go to the next stage 
    // 
    next() 

}); 

APIキーチェックの私の実装の例です。

+0

ありがとうございます、今は本当に明らかです。ちょうど2つの質問。 1)HTTPSクライアント/サーバー側(サーバー側の証明書を除く)を処理するために、特定のものを設定する必要がありますか。 nginxをセットアップする必要がありますか? 2)どのようにenv.API_KEYを管理しますか?これは単に 'export EDITOR = emacs'を設定するような単純なシステム変数です。また、クライアント側をどのように管理しますか?同じコードですが、逆になります(送信前に文字列をエンコードしますか?)。ありがとう – Ragnar

+0

多くの質問:)コメントセクションには制限された文字があるので、私はそれぞれの質問に別々のコメントで答えます。 –

+0

** HTTPS **:これを行うにはさまざまな方法がありますが、どれがアプリケーションをホストするかによって異なります。あなたがHerokuでホストしている場合、あなたはあなたの側で何もする必要はありません、あなたは彼らの側でSSLを有効にするので、そこにそれを行う方法をGoogleにする必要があります。あなたが自分でそれを撮影した場合、私の記事でSSLを追加する方法を聞くことができます。これは簡単です:https://github.com/davidgatti/IoT-Raw-Sockets-Examples/tree/master/Templates/NodeJS/tls。それ以外のものはあなたに依存します:) –

1

私はちょうど私の認証部分を終了しました。AngularJSアプリケーション。答えはJWTPassportとなるため、データ/ APIを保護するために優れた技術を使用する必要があります。

JWTライブラリを使用する場合は、認証のためにhttpヘッドを保持するのに役立ちます。

私が使用したコードの一部:

app.js

var jwt = require('express-jwt'); 

var auth = jwt({ 
    secret: config.jwt.secret, 
    userProperty: 'payload' 
}); 

app.use('/api/secret', auth, apiSecretRoutes); 

login.js

module.exports.login = function (req, res) { 
    if (!req.body.username || !req.body.password) { 
     return tools.sendJSONresponse(res, 400, { 
      message: 'All fields required!' 
     }); 
    } 

    passport.authenticate('local', function (err, user, info) { 
     var token; 
     if (err) { 
      return tools.sendJSONresponse(res, 404, err); 
     } 

     if (user) { 
      token = user.generateJwt(); 
      return tools.sendJSONresponse(res, 200, { 
       ok: true, 
       message: 'welcome ' + user.name, 
       token: token 
      }); 
     } else { 
      return tools.sendJSONresponse(res, 400, info); 
     } 
    })(req, res); 
}; 

ユーザー。JS

userSchema.methods.generateJwt = function() { 
    var expiryDays = 1; 
    var expiry = new Date(); 
    expiry.setDate(expiry.getDate() + expiryDays); 

    return jwt.sign({ 
     _id: this._id, 
     username: this.username, 
     name: this.name, 
     exp: parseInt(expiry.getTime()/1000) 
    }, config.jwt.secret); 
}; 

その他の参考文献:

+1

ありがとうございます。しかし、私はユーザー名とパスワードでユーザー認証をする必要はありません。これは、要求とデータを保護するための内部APIです。ユーザーが自分のアプリの使用状況を把握したり、アプリの一部のアクセスを拒否したりすることをユーザーに許可することはありません。私はこの種の認証を遅かれ早かれ使用する方法が必要になるので、ちょっと感謝します。 – Ragnar

関連する問題