web-dev-qa-db-ja.com

JSESSIONIDを使用してJavaセッションを手動でロードするにはどうすればよいですか?

マルチパートフォームポストを処理するサーブレットがあります。投稿は、実際にはページに埋め込まれたFlashファイルアップロードコンポーネントによって行われています。一部のブラウザでは、Flashで生成されたPOSTにJSESSIONIDが含まれていないため、投稿中に特定の情報をセッションから読み込むことができません。

フラッシュアップロードコンポーネントには、特別なフォームフィールド内にCookieとセッション情報が含まれています。このフォームフィールドを使用して、実際にJSESSIONID値を取得できます。問題は、このJSESSIONID値を使用して特定のセッションを手動でロードする方法がわからないことです。

編集- ChssPly76のソリューションに基づいて、次のHttpSessionListener実装を作成しました。

    @Override
    public void sessionCreated(final HttpSessionEvent se) {
        final HttpSession session = se.getSession();
        final ServletContext context = session.getServletContext();
        context.setAttribute(session.getId(), session);
    }

    @Override
    public void sessionDestroyed(final HttpSessionEvent se) {
        final HttpSession session = se.getSession();
        final ServletContext context = session.getServletContext();
        context.removeAttribute(session.getId());
    }

これにより、すべてのセッションがServletContextに一意のIDによってマップされる属性として追加されます。代わりにコンテキストにセッションのマップを入れることもできますが、冗長なようです。この決定についての考えを投稿してください。次に、次のメソッドをサーブレットに追加して、IDによってセッションを解決します。

    private HttpSession getSession(final String sessionId) {
        final ServletContext context = getServletContext();
        final HttpSession session = (HttpSession) context.getAttribute(sessionId);
        return session;
    }
28
Robert Campbell

IDでセッションを取得するAPIはありません。

ただし、できることは、Webアプリケーションに セッションリスナー を実装し、IDをキーとするセッションのマップを手動で維持することです(セッションIDは session.getId() で取得できます) =)。その後、必要なセッションを取得できます(コンテナをだまして、現在のセッションを他の人が示唆するように置き換えます)

23
ChssPly76

これを行う安全な方法は、cookieにjsession idを設定することです。これは、urlに設定するよりもはるかに安全です。

Cookieとして設定されると、通常の方法でセッションを取得できます

request.getSession();

method.setRequestHeader("Cookie", "JSESSIONID=88640D6279B80F3E34B9A529D9494E09");
2
vanval

サーブレット仕様内に方法はありませんが、次を試すことができます。

  • flashによって行われたリクエストでCookieを手動で設定する

  • または、jsessionidパラメーターをURIのパスに入力して追加したときに、Taylor Lが提案したとおりに実行します。

どちらの方法も、Tomcatのように動作するサーブレットコンテナーでの実行にアプリを関連付けます。それらのほとんどがそうだと思います。どちらの場合も、ページにCookieを要求するFlashアプレットが必要です。これにより、JavaScriptの依存関係が発生する可能性があります。

1
Andrew Duffy

Tomcatを使用している場合は、Tomcatに直接問い合わせます(ただし、見苦しいです)。他のWebサーバー用のその他のハッキングソリューションがあるに違いありません。

「Manager」インターフェイスのインスタンスを使用して、セッションを管理します。見苦しいのは、接続できるニースのパブリックインターフェイスが見つからないため、マネージャーを取得するためにリフレクションを使用する必要があることです。

以下は、コンテキストの起動時にそのマネージャーを取得し、Tomcatセッションを取得するために使用できるコンテキストリスナーです。

public class SessionManagerShim implements ServletContextListener {
    static Manager manager;

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        try {
            manager = getManagerFromServletContextEvent(sce);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        manager = null;
    }

    private static Manager getManagerFromServletContextEvent(ServletContextEvent sce) throws NoSuchFieldException, IllegalAccessException {
        // Step one - get the ApplicationContextFacade (Tomcat loves facades)
        ApplicationContextFacade contextFacade = (ApplicationContextFacade)sce.getSource();

        // Step two - get the ApplicationContext the facade wraps
        Field appContextField = ApplicationContextFacade.class.getDeclaredField("context");
        appContextField.setAccessible(true);
        ApplicationContext applicationContext = (ApplicationContext)
                appContextField.get(contextFacade);

        // Step three - get the Context (a Tomcat context class) from the facade
        Field contextField = ApplicationContext.class.getDeclaredField("context");
        contextField.setAccessible(true);
        Context context = (Context) contextField.get(applicationContext);

        // Step four - get the Manager. This is the class Tomcat uses to manage sessions
        return context.getManager();
    }

    public static Session getSession(String sessionID) throws IOException {
        return manager.findSession(sessionID);
    }
}

これをweb.xmlのリスナーとして追加すると、動作するはずです。

その後、これを実行してセッションを取得できます。

0
Sam Sieber

これは本当に良い投稿です。セッションリスナを使用してコンテキストにセッションを追加し続けることで発生する可能性のある問題の1つは、同時セッションの数に応じてかなり太くなる可能性があることです。そして、リスナーのWebサーバー構成に関するすべての追加作業。

それでは、もっと簡単な解決策についてはどうでしょう。これを実装しましたが、非常にうまく機能します。そのため、フラッシュアップロードオブジェクトを読み込むページで、セッションとセッションIDをキーと値のペアとしてアプリケーションオブジェクトに保存し、そのセッションIDをpostパラメーターとしてアップロードページに渡します。アップロードページで、そのセッションIDが既にアプリケーションにあるかどうかを確認し、そのセッションを使用するか、そうでない場合はリクエストからセッションを取得します。また、先に進み、そのキーをアプリケーションから削除して、すべてをきれいに保ちます。

Swfページ:

application.setAttribute(session.getId(), session);

次に、アップロードページで:

String sessid = request.getAttribute("JSESSIONID");
HttpSession sess = application.getAttribute(sessid) == null ?
        request.getSession() :
        (HttpSession)application.getAttribute(sessid);
application.removeAttribute(sessid);

非常に素晴らしい解決策の人。これをありがとう。

0
Garfield