6

Jetty 8.1、dojo、cometdを使用するWebアプリケーションがあり、(1)同期操作用のJSON / HTTP REST APIと(2)サーバーから多数のイベントを受信するcometdAPIを使用してブラウザーとWebコンテナー間で対話します。

特にcometdは可能な限り通常のHTTPの代わりにwebsocketを使用するため、これら2つの異なるAPIの認証セッションをエレガントに管理する方法については完全には明確ではありません。アプリケーションは、標準のJettyLDAPモジュールを使用したフォームベースの認証を使用しています。したがって、HTTPの観点からは、コンテナはブラウザに次のような標準のjsessionidを提供します。

Cookie: jsessionid=758E2FAD7C199D722DA8B5E243E0E27D

ここでのSimoneBordetの投稿に基づくと、推奨される解決策は、cometdハンドシェイク中にこのトークンを渡すことです。これは私たちが行っていることです。

私たちが抱えている問題は、HTTPセッションとBayeuxcometdセッションの2つの根本的に異なるセッションがあることです。潜在的なメモリリークやセキュリティの問題などの理由で、それらを一斉に終了するか、「ペアリング」する必要があります。ユーザーのHTTPセッションが終了した場合、対応するBayeuxセッションも終了する必要があります。その逆も同様です。これを行うための推奨される方法はありますか?

4

2 に答える 2

12

HTTPセッションとCometDセッションのライフサイクルは異なります。たとえば、一時的な接続障害が発生した場合、CometDセッションは失敗し、サーバーはクライアントに再ハンドシェイクを要求するため、別のCometDセッションが作成されます(同じユーザーですが、CometDが異なりますclientId)。同じ場合、はHttpSession同じままになります。

HttpSessionこれを念頭に置いて、ユーザー名、コレスポンデント、およびコレスポンデントの間のマッピングをアプリケーションレベルで維持する必要がありますServerSession。このマッピングを呼びましょうHttpCometDMapper。新しいユーザーがログインするたびに、その名前(またはユーザーの別の一意の識別子)、、、HttpSessionおよび現在のを登録しServerSessionます。HttpSessionおそらく、最初にユーザー名とをリンクし、次に同じユーザー名を。とリンクする2段階のプロセスが必要になりますServerSession

CometDの再ハンドシェイクが実行された場合は、マッパーを新しいで更新しますServerSession

HttpSessionListenerを登録することで2つのセッションをリンクできます。これにより、破壊されたときに、マッパーからHttpSession現在のCometDを取得して呼び出すことができます。ServerSessionServerSession.disconnect()

CometDには、持っているような非アクティブタイムアウトの概念がないため、その逆は少し注意が必要HttpSessionです。独自のロジックを使用してアプリケーションに実装する必要があります。

それを行うことの一部は、次のようRemoveListenerににを登録することです。ServerSession

serverSession.addListener(new ServerSession.RemoveListener() 
{
    public void removed(ServerSession session, boolean timeout);
    {
        if (!timeout)
        {
            // Explicitly disconnected, invalidate the HttpSession
            httpCometDMapper.invalidate(session);
        }
    }
});

このリスナーは、クライアント(およびサーバー-再入可能性に注意)からの明示的な切断を監視します。

少し難しいのは、非明示的な切断に同じメカニズムを実装することです。この場合、timeoutパラメーターはtrueになりますが、一時的なネットワーク障害が原因で発生した可能性があり(クライアントが完全に消えるのではなく)、同じユーザーが既に新しいを使用して再ハンドシェイクしている可能性がありますServerSession

この場合、アプリケーションのタイムアウトで問題を解決できると思います。タイムアウトがServerSession原因で削除されたことが表示されたら、そのユーザーに注意してアプリケーションのタイムアウトを開始します。同じユーザーが再ハンドシェイクする場合は、アプリケーションのタイムアウトをキャンセルします。そうしないと、ユーザーが実際にいなくなり、アプリケーションのタイムアウトが期限切れになり、ユーザーも無効になりHttpSessionます。

上記は単なるアイデアと提案です。実際の実装は、アプリケーションの詳細に大きく依存します(そのため、CometDはそのままでは提供されません)。

重要なポイントは、マッパー、HttpSessionListenerおよびRemoveListener、およびこれらのコンポーネントのライフサイクルを知ることです。それを管理したら、アプリケーションに適切なことを行う適切なコードを記述できます。

最後に、CometDにはHttpSession、インスタンスを介してトランスポートに依存しない方法で対話する方法があることに注意してください。BayeuxContextこれは、から取得できますBayeuxServer.getContext()。特に、に格納されているトークンを取得する場合に、それが物事を単純化できるかどうかを確認するためにも、それを確認することをお勧めしますHttpSession

于 2012-05-30T17:56:40.670 に答える
0

一時的な接続障害の後にBayeuxClientを作成しようとすると、問題が発生しますか?

以下のコードで試すことができます。

    try {
        log.info("Running streaming client example....");
        makeConnect();


    } catch (Exception e) {
        handleException("Error while setup the salesforce connection.", e);
    }
}



private void makeConnect() {
    try{
        client = makeClient();
        client.getChannel(Channel.META_HANDSHAKE).addListener
                (new ClientSessionChannel.MessageListener() {
                    public void onMessage(ClientSessionChannel channel, Message message) {
                        log.info("[CHANNEL:META_HANDSHAKE]: " + message);
                        boolean success = message.isSuccessful();
                        if (!success) {
                            String error = (String) message.get("error");
                            if (error != null) {
                                log.error("Error during HANDSHAKE: " + error);
                            }

                            Exception exception = (Exception) message.get("exception");
                            if (exception != null) {
                                handleException("Exception during HANDSHAKE: ", exception);
                            }
                        }
                    }
                });

        client.getChannel(Channel.META_CONNECT).addListener(
                new ClientSessionChannel.MessageListener() {
                    public void onMessage(ClientSessionChannel channel, Message message) {
                        log.info("[CHANNEL:META_CONNECT]: " + message);
                        boolean success = message.isSuccessful();

                        if (!success) {
                            client.disconnect();
                            makeConnect();
                            String error = (String) message.get("error");
                            if (error != null) {
                                //log.error("Error during CONNECT: " + error);
                            }
                        }
                    }

                });

        client.getChannel(Channel.META_SUBSCRIBE).addListener(
                new ClientSessionChannel.MessageListener() {
                    public void onMessage(ClientSessionChannel channel, Message message) {
                        log.info("[CHANNEL:META_SUBSCRIBE]: " + message);
                        boolean success = message.isSuccessful();
                        if (!success) {
                            String error = (String) message.get("error");
                            if (error != null) {
                                makeConnect();
                                log.error("Error during SUBSCRIBE: " + error);
                            }
                        }
                    }
                });
        client.handshake();
        log.info("Waiting for handshake");
        boolean handshaken = client.waitFor(waitTime, BayeuxClient.State.CONNECTED);
        if (!handshaken) {
            log.error("Failed to handshake: " + client);
        }
        log.info("Subscribing for channel: " + channel);
        client.getChannel(channel).subscribe(new MessageListener() {
            public void onMessage(ClientSessionChannel channel, Message message) {
                injectSalesforceMessage(message);
            }
        });
        log.info("Waiting for streamed data from your organization ...");
    }catch (Exception e) {
        handleException("Error while setup the salesforce connection.", e);
    }

}
于 2015-11-12T06:11:23.703 に答える