2016-07-28 9 views
1

私はsocket.io-jwtパッケージを使用して自分のユーザーをSocket.ioに認証するために、nJWTパッケージを介してJWTトークンを使用しています。JWTトークンの使用。より良いアプローチがありますか?

多かれ少なかれ、コードは次のようになります。ユーザーはJWTトークンを生成するためにHTMLフォームを介して再生/ログインするPOST要求を送信します。次に、socket.ioクライアントはそのトークンを使用して初期化されます。今

/** 
* Create Express server. 
*/ 
const app = express(); 
const http = require('http').Server(app); 
const io = require('socket.io')(http); 
const socketioJwt = require('socketio-jwt'); 

app.set('jwt.secret', secureRandom(256, { 
    type: 'Buffer' 
})); 

app.post('/play/login', (req, res) => { 
    // validate user's req.body.email and req.body.password 

    const claims = { 
     iss: "http://app.dev", // The URL of your service 
     sub: "user-1", // The UID of the user in your system 
     scope: "game" 
    }; 

    const jwt = nJwt.create(claims, app.get("jwt.secret")); 
    const token = jwt.compact(); 

    new Cookies(req,res).set('access_token', token, { 
     httpOnly: true, 
     secure: process.env.ENVIRONMENT === "production" 
    }); 

    tokenUserRelations[token] = req.body.email; 

    res.json({ 
     code: 200, 
     token: token 
    }); 
}); 

/** 
* Add Socket IO auth middleware 
*/ 
io.set('authorization', socketioJwt.authorize({ 
    secret: app.get("jwt.secret"), 
    handshake: true 
})); 

io.sockets.on('connection', function (socket) { 

    socket.on('chat message', function (req) { 
     io.emit("chat message emit", { 
      email: tokenUserRelations[socket.handshake.query.token], 
      msg: req.msg 
     }); 
    }); 

    socket.on('debug', function (req) { 
     io.emit("debug emit", { 
      playersOnline: Object.keys(tokenUserRelations).length 
     }); 
    }); 

    socket.on('disconnect', function (req) { 
     delete tokenUserRelations[socket.handshake.query.token]; 
    }); 
}); 
io.listen(app.get('socket.port'),() => { 
    console.log('Started! Socket server listening on port %d in %s mode', app.get('socket.port'), app.get('env')); 
}); 

、それが正常に動作しますが、トークンからのメールを追跡するために、私はこれをしなければならなかった:

tokenUserRelations[token] = req.body.email; 

ので、私はどのユーザートークンポイントを関連付けることができます。

グローバルオブジェクト内のトークンを維持することは、特にトークン/クッキーが期限切れになったときに私の頭痛を引き起こす原因になると感じています。

これについてもっと良い方法はありますか? JWTトークンがどのユーザーを指しているのかを知る必要がありますので、ビジネスロジックを実行できます。

ありがとうございます。

答えて

1

トークンには任意の情報が含まれ、この情報はトークンに沿って暗号化されています。

トークンのユーザーIDを暗号化します。要求を受け取ったときにトークンを復号化します(検証時に実行されます)。ユーザーIDは通常通り使用します。

トークンが期限切れになると、新しいトークンは同じユーザーIDを持ち、コードには影響しません。

これは私のウェブアプリケーションの1つで、これはうまくいきました。しかし、私は使用していたofficial jwt module

+0

リクエストがソケットエンドポイントにヒットするたびにトークンを復号化するはずですか?もしそうなら:A.私のすべてのsocket.ioエンドポイントにミドルウェアより前にグローバルを設定する方法はありますか? B:解読がCPU消費タスクになる可能性があるため、パフォーマンスには大きな影響はありませんか? – Aris

+1

はい、トークンを検証する方法であり、サーバー側を覚えておくことではありません。エクスプレスでは、はい、しかし私はsocket.ioについて知らない。存在するが、それ以外の認証スキームはない。 – DrakaSAN

+0

違うアプローチがあると思いませんか?毎回トークンの復号化と再検証は素晴らしいとは言えません。特に、私はソケット呼び出しをたくさん得ているので、パフォーマンスは賢明です。 (私はたくさんのソケットが縛られているゲームを開発しています)ソケットの目的は両側の安全なハンドシェイクを識別することだと思ったので、コール中に追加のコントロールを必要とせずにすべてのトランザクションを安全に行うことができます。リアルタイムプログラミングに精通していないと誤解されているかどうかはわかりません。 – Aris

1

tokenUserRelationsの作成方法やメンテナンス方法については、コードに何も表示されませんが、「グローバル」と聞くと直ちに赤い旗が上がります。

JWT標準には、トークン自体に「クレーム」を埋め込むという概念が含まれています。 claims定数で既にそうしています。そのデータ形式は任意であり、JWT全体が検証される限り、アプリケーションによって信頼されることができます。リクエストごとにJWTを確認する必要があることに注意してください。だから、その主張のオブジェクトに電子メールを詰め込むだけで大丈夫ではない、それはほとんどの人がやっていることです。

サイドノートとして、あなたは今あなたの 'jwt.secret'をどのように設定しているかについて注意する必要があります。今あなたが持っているものは、アプリケーションが起動するたびに新しいものを生成します。つまり、a)すべてのユーザはログアウトされ、アプリが再起動するたびに再ログインする必要があります。b)複数のプロセス、または複数のサーバーを必要とする場合は、将来的にそれを実行できます。

デバッグの目的以外では、アプリケーションの起動時に生成するよりも環境(たとえばenv var)から取得するほうがよいです。

+0

userRelationsは基本的なハッシュテーブルです。ここでkeyはトークンで、valueは電子メールです。セキュリティ上の理由からトークンの内部に情報を置くことには慎重でした。そのため、私はそれらをサーバー側に置いておきたいのです。 はい、アプリを再起動すると、トークンが無効になります。私は今から.envでそれを保つつもりです。 正しい/安全なアプローチは、 'claim'オブジェクトに情報を追加し、各ソケット呼び出しで' socket.handshake.query.token'を検証し、トークンを解読して情報を取得することです。 – Aris

+0

はい、JWTトークンを使用するように設計されています。 – Paul

1

上記の優れた答えに加えて、jwt.secretをファイルに保存し、コードが読み込まれてgitリポジトリに追加されていない場合はそれを取り込むことも重要です使っている)。 .gitignoreファイルに 'jwt.secret'へのパスを含めるようにしてください。プロダクションコードをデプロイする準備ができたら、そのキーを推奨する環境変数として設定します。また、リセットする必要がある場合は、ローカル環境でそのキーのレコードを取得します。

JWTを使用すると、apiを保護する優れた便利な方法ですが、ベストプラクティスに従うことが不可欠です。

+0

私は '.env'を使います。私は秘密が毎回違っていたと思った。再起動後に無効なトークンが私の心に大きな疑問を投げかけていたので、私は '.env'に頼ることができてうれしいです。 :) – Aris

+0

間違いなく!トークンをチェックし、もしあれば再発行を強制することによってトークンが期限切れになるように設定することもできます。 – alexi2

+0

さようなら!ちゃんと覚えておきますよ。ところで、お父さんであることをお祝いします。 :) – Aris

関連する問題