socket.ioとセッション?


95

エクスプレスフレームワークを使用しています。socket.ioからセッションデータにアクセスしたい。client.listener.server.dynamicViewHelpersデータでdynamicHelpersを表現しようとしましたが、セッションデータを取得できません。これを行う簡単な方法はありますか?コードをご覧ください

app.listen(3000);

var io = require('socket.io');
var io = io.listen(app);

io.on('connection', function(client){
    // I want to use session data here
    client.on('message', function(message){
        // or here
    });
    client.on('disconnect', function(){
        // or here
    }); 
});

5
または、この非常に良い
Fabiano Soriani

3
@FabianoPS-もう動作しません-connectは、これが依存するparseCookieメソッドを提供しなくなりました。
UpTheCreek

1
@UpTheCreek-connectはparseCookieメソッドを使用しなくなったので、これはどのようにして可能ですか?
アウスト・

@Aust-良い質問です。今のところ、最善の方法はわかりません。これは本当に混乱したIMOです。厄介なことに、ほとんどの回避策の議論は、socket.ioにも当てはまります(誰もがsocket.ioを使用しているわけではありません!)現在、parseSignedCookie関数がありますが、それも非公開であるため、変更を破壊するリスクもあります。
UpTheCreek

2
Socket.IO(1.1)およびエクスプレス(4.xの)の新しいバージョンでは、このSOの質問を確認してください。stackoverflow.com/questions/25532692/...
pootzko

回答:


68

これは、flashsocketトランスポートを経由するソケットには機能しません(サーバーに必要なcookieを送信しません)が、他のすべてに対して確実に機能します。コードでflashsocketトランスポートを無効にするだけです。

それを機能させるために、エクスプレス/接続側で、セッションストアを明示的に定義して、ソケット内で使用できるようにします。

MemoryStore = require('connect/middleware/session/memory'),
var session_store = new MemoryStore();
app.configure(function () {
  app.use(express.session({ store: session_store }));
});

次に、ソケットコード内に接続フレームワークを含めて、Cookie解析を使用してCookieからconnect.sidを取得できるようにします。次に、そのconnect.sidがあるセッションストアでセッションを次のように検索します。

var connect = require('connect');
io.on('connection', function(socket_client) {
  var cookie_string = socket_client.request.headers.cookie;
  var parsed_cookies = connect.utils.parseCookie(cookie_string);
  var connect_sid = parsed_cookies['connect.sid'];
  if (connect_sid) {
    session_store.get(connect_sid, function (error, session) {
      //HOORAY NOW YOU'VE GOT THE SESSION OBJECT!!!!
    });
  }
});

その後、必要に応じてセッションを使用できます。


3
socket_client.requestは、socket.io-nodeの最新バージョンで削除されたようです
Art

6
注意してください...これを行うには新しい規則があります...代わりにSocket.IO認証を使用することをお勧めします。@Jefferの投稿を参照
BMiner

2
残念ながら、これはもう機能しません-parseCookieは接続ユーティリティの一部ではなくなりました。どうやらそれは決してパブリックAPIの一部ではありませんでした。そこ厄介な代替だ- parseSignedCookieが、これは、またプライベートで私は...あまりにも消えるのリスクがその推測をして
UpTheCreek

今、私はこれについて考えています...クッキーのストアとソケットのストアを同じストアに設定しないのはなぜですか?
James

34

Socket.IO-sessionsモジュールソリューションは、クライアント(スクリプト)レベルでセッションIDを公開することにより、アプリをXSS攻撃にさらします。

代わりにこのソリューションを確認してください(Socket.IO> = v0.7の場合)。こちらのドキュメントをご覧ください


1
@Jeffer-その2番目のソリューションは、現在のバージョンの接続では機能しなくなります。
UpTheCreek

2
-1 socket.ioは、そのモジュールではなく、セッションIDを公開するものです。セッションIDはクライアント側でcookieに保存されるため、これは大した問題ではありません...また、そのチュートリアルはExpressの最新バージョンでは機能しません。
Aust

1
ソリューションリンクは単にsocket.iogithubページにリダイレクトされます。
TJ

8

ホイールを完全に再発明しないことをお勧めします。必要なツールはすでにnpmパッケージです。これはあなたが必要とするものだと思います:session.socket.io 私は最近このツールを使用しています。エクスプレスセッションをsocket.ioレイヤーにリンクすると、非常に多くの利点があります。


6
ここで担体はsocket.io> = 1.0のsocket.io-セッション発現することを更新モジュールである github.com/xpepermint/socket.io-express-session
blnc

4

編集:機能しないいくつかのモジュールを試した後、私は実際に行ってこれを行うために自分のライブラリーを作成しました。恥知らずなプラグイン:https://github.com/aviddiviner/Socket.IO-sessionsでチェックしてください。私は歴史的な目的のために以下の古い投稿を残しておきます:


上記のpr0zacの解決策のように、flashsocketトランスポートをバイパスする必要なしに、私はこの作業をきちんと手に入れました。Socket.IOでExpressも使用しています。方法は次のとおりです。

まず、セッションIDをビューに渡します。

app.get('/', function(req,res){
  res.render('index.ejs', {
    locals: { 
      connect_sid: req.sessionID
      // ...
    }
  });
});

次に、ビューでSocket.IOクライアント側にリンクします。

<script>
  var sid = '<%= connect_sid %>';
  var socket = new io.Socket();
  socket.connect();
</script>
<input type="button" value="Ping" onclick="socket.send({sid:sid, msg:'ping'});"/>

次に、サーバー側のSocket.IOリスナーでそれを取得し、セッションデータの読み取り/書き込みを行います。

var socket = io.listen(app);
socket.on('connection', function(client){
  client.on('message', function(message){
    session_store.get(message.sid, function(error, session){
      session.pings = session.pings + 1 || 1;
      client.send("You have made " + session.pings + " pings.");
      session_store.set(message.sid, session);  // Save the session
    });
  });
});

私の場合、私session_storeredis-connectライブラリを使用しているRedis です。

var RedisStore = require('connect-redis');
var session_store = new RedisStore;
// ...
app.use(express.session({ store: session_store }));

これがGoogleを検索しているときにこの投稿を見つけた人に役立つことを願っています


8
セキュリティの観点からは、クライアントIDにセッションIDを配置することはお勧めできません...
UpTheCreek

4
セッションIDがすでにローカルCookieに格納されているのに、なぜHTMLにセッションIDを置くのが悪い考えなのですか?
Gavin

3
HttpOnly cookieとして設定すると、JavaScriptからcookieにアクセスできないためです。HTMLにsession.sidを配置することにより、攻撃者がDOMで必要とするすべてのものを与えることができます。
rochal 2015年

3

これを見てください:Socket.IO Authentication

オブジェクトに直接接続されていないため、client.request...または何もフェッチしないことをお勧めします。常に最後にログインしたユーザーをポイントします。client.listener...client


2

Socket.IO-connectを確認する

Socket.IO-nodeの周りにWebSocketミドルウェアラッパーを接続します https://github.com/bnoguchi/Socket.IO-connect

これにより、Socket.IOイベントハンドラで処理する前に、Socket.IOリクエストをExpress / Connectミドルウェアスタックにプッシュして、セッションやCookieなどにアクセスできるようになります。ただし、Socket.IOのすべてのトランスポートで動作するかどうかはわかりません。


残念ながら、モジュールがまだsocket.ioのv0.6を使用していること
fent

2

express-socket.io-sessionを利用できます。

cookieベースの高速セッションミドルウェアをsocket.ioと共有します。express> 4.0.0およびsocket.io> 1.0.0で動作し、下位互換性はありません。

私のために働いた!!


ねえ。フロントエンドでセッション値をどのように使用しますか?npm docsでそれらを見ることができません。
Hari Ram

1

あなたはこれを見ることができます:https//github.com/bmeck/session-web-sockets

または、代わりに以下を使用できます。

io.on('connection', function(client) { 
  var session = client.listener.server.viewHelpers; 
  // use session here 
});

お役に立てれば。


私はセッションWebソケットを知っていますが、これにライブラリを使用したくありません。簡単な解決策を探しています。私はclient.listener.server.viewHelpersを試しました。しかし、これは次を返しました:{}
sfs

2
これは最初はうまくいくように見えますが、レースコンディションにつながります。完全に回避することをお勧めします。
シュリパッドクリシュナ

1

私がそれを正しく行っているかどうかはわかりません。 https://github.com/LearnBoost/socket.io/wiki/Authorizing

ハンドシェイクデータを使用して、Cookieにアクセスできます。また、Cookieで、各クライアントのセッションIDであるconnect.sidを取得できます。次に、connect.sidを使用してデータベースからセッションデータを取得します(RedisStoreを使用していると想定しています)


これはまさに進むべき道ですが、あなたのクールではないので、スタックオーバーフローポイントを得ることができません。github.com/tcr/socket.io-sessiongithub.com/functioncallback/session.socket.io私は最初のほうが少しクリーナーが良いのが好きです。2つ目は、ドキュメントが少し良くなっています。
ジェームズ

@TJ申し訳ありませんが、答えが2年前だったことをご存知ですか?そして、おそらく今は機能しないでしょう
Tan Nguyen

@TanNguyen知っている、だから私はあなたに通知を更新して、人々にデッドリンクを指すよりも必ず答えを更新できるように通知したのです
TJ

@TJありがとうございます。残念ながら、2年前のパフォーマンスの問題により、socket.ioから離れました。したがって、私はsocket.ioでセッションを扱うの現在の方法であるかわからない
タングエンを
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.