12

リアルタイム サポートを追加したい、動作中の php アプリケーションがあります。そのような機能を追加するために nodejs/socket.io を使用したいと思います。

私が見つけた最初の問題は、nodejs 側でユーザーを適切に認証する方法でした (ユーザーは PHP セッションを介して PHP バックエンドで既に認証されています)。nodejs側でsocket.handshake.header.cookieを使用すると、PHPセッションIDを解析して取得できます。これは、redis/memcache/databaseを介して認証できます(セッション情報の保存に何を使用したかによって異なります)。
ユーザーがサイトのタブ/ウィンドウを1つしか開いていない場合、すべてがクールに見えます-複数のタブ/ウィンドウを使用してsession_regenerate_id()を使用する場合、nodejsでは、ユーザーは別のsessionidキーで認証されるため、接続したソケットID以外では2つのタブを区別できません。ユーザーがログアウトすると、どのタブにもメッセージが表示されないはずです (そのブラウザーからすべてのタブ/ウィンドウで既にログアウトしているため)。そのため、ログアウト メッセージ (ログアウトの直前にブラウザから送信された PHP のもの) で、承認されたユーザー ID に接続されているすべてのソケット接続を削除する必要があります。しかし、ユーザーが 2 つのデバイス (fe. PC ブラウザーと iPad サファリ) でログインした場合はどうなるでしょうか。1 つのデバイスでログアウトした後、すべてのデバイスではなく、ログアウトしたデバイスでメッセージを受け取るべきではありません。socket.io で異なるデバイス/ブラウザからの接続を区別するにはどうすればよいですか? もちろん、session_regenerate_id()を使用していませんここでは効率的ですが、本当にこの機能を使用したい場合はどうすればよいですか?

私が抱えているもう 1 つの問題は、むしろセキュリティの問題 (または疑問) です。アプリケーションの許可されたユーザーがページexample.com/user1 (user1 のニュース フィード) を表示でき、example.com /user2 を表示できないと仮定します(fe. 彼にはそれを表示する権限がありません)。ユーザーがexample.com/user1にいるときに socket.io がブラウザに更新メッセージを送信し、もちろんユーザーがexample.com/user2サイトにいるときに送信しないようにしたいと思います。socket.io 側では、リファラー アドレスを読み取ることができます (おそらく、ユーザーが user2 サイトにいる場合、彼は socket.io 接続を取得しません)。質問は:リファラー アドレスと node.js 側の認証済みユーザーの権利を比較する必要がありますか? それとも、リファラーの値はnode.js 側で安全ですか? node.js 側に別の db チェックを追加すると、速度が低下します (ほぼすべてのリクエストで、PHP と node.js の 2 つの側で同じデータベース チェックが必要になるため)。

それとも、私が提示した方法で動作する socket.io + PHP アプリケーションの概念全体が間違っているのでしょうか?

UPDATE

最初の質問の問題を省略する方法を見つけたと思います-基本的には、別のCookie(PHPSESSID以外)を追加するだけです。NODESESSID という名前で、ユーザーが承認されたときに生成します (fe. uniqid() を使用)。現在、node.js 側での認証は、PHPSESSID と NODESESSID を比較しています (両方が一致する必要があります)。ここで、ユーザーがログアウトすると、メッセージlogoutが socket.io に配信され、socket.io は NODESESSID ですべてのソケットを切断します。これは、セッション ID を再生成することと、セッション ID を再生成しないことの利点を結びつけるようなものです (ただし、セッション固定に対して脆弱ではありませんよね?)。

4

2 に答える 2

1

2 番目の質問について:

コメントに記載されているように、リファラーは安全ではありません。

私は自分のアプリケーションで同様の問題を抱えており、これが私にとってどのように機能するかです。

まず、すべてのトラフィックがソケットを通過する単一ページのアプリがありますが、それは必要ありません。あなたが管理した方法でもセッションで動作するはずです。

nodejs onConnect では、ユーザーが認証されているかどうかをバックエンドに尋ね、ユーザー ID をソケット オブジェクト (socket.data) に格納し、ハッシュマップを作成してユーザー ID から直接ソケットを検索します。

次に、Redis を使用し、nodejs から redis リストにサブスクライブします ( redis pub/sub を参照)。PHP バックエンドは、メッセージに対処するためのユーザー ID を使用して、このリストにメッセージをプッシュします。nodejs はこのメッセージ (新しいニュース フィード アイテムなど) を取得し、前述のハッシュマップでユーザー ID を検索し、それをクライアントに送信します。そのため、ユーザーは許可されているものだけを取得します。次に、クライアントはメッセージをどう処理するかを決定します。ユーザーが自分のフィード ページにいる場合は、アイテムを追加できます。ユーザーが他の人のフィードにいる場合は、ページの別の場所に通知を追加するだけです。破棄することもあります。

PHP バックエンド サイトでは、このメッセージは、接続されたクライアントでライブで表示する必要があるイベントが発生するたびに、redis に送信されます。user1 が user2 のフィードに投稿すると、新しいアイテムがデータベースに保存され、同時にメッセージとして redis キューに送信されます。

このシステムは、接続されたユーザーがすでに認証されていることを確認するために nodejs がデータベースにクエリを実行するだけでよいため、DB の負荷を軽減するのにも役立ちます。

于 2012-09-05T11:33:09.657 に答える
-1

実際には、node.js の使用を避け、phpdaemonを使用できます。これは php で記述されており、非常にうまく機能します。

于 2012-10-02T07:22:37.900 に答える