java - Servlet 如何通过一般请求参数传递 SessionID
天蓬老师
天蓬老师 2017-04-17 17:57:18
0
2
833

我有个项目,希望在 REST 接口使用 SessionID 作为 Token,这样能简化和用熟悉的方式处理会话数据,在 URL 附加 ;jsessionid= 太丑,传递 Cookie 的话 APP 开发又嫌麻烦,就想通过普通的 GET/POST 参数或自定义 HTTP BODY 来传递 SessionID。

现在的 Servlet 都不再支持通过 ID 获取 Session,搜到的一些方案,比如用监听器来记录 Session,但我不喜欢这种方式,1是我觉得冗余,2是不想自己存储更不想放在内存里;SessionManager 的话就是自定存储了,目前 tomcat,jetty 等的 session 已经满足我的需求了,没必要找这个麻烦。

我查了下 Tomcat 的源码找到了他的 Request 里有 setRequestedSessionId 的方法,只要在 getSession 之前调用就行,但这不是 ServletRequest 接口里的方法,我的项目不一定运行在 Tomcat 里。

来问问有什么简单的方式解决这个问题没?

天蓬老师
天蓬老师

欢迎选择我的课程,让我们一起见证您的进步~~

全部回覆(2)
Peter_Zhu

搞定了,我查了Tomcat,Jetty 各自的Request (HttpServletRequest 的實作),都透過一個setRequestedSessionId(String) 來設定會話id,如是我用反射的方式來取得和呼叫此方法,在getSession 之前設定sessionId,經過在Jetty 上實驗有效,再去試試Tomcat。這兩種容器是我常用的,遇到其他容器再看了。

程式碼簡簡單單:

    try {
        request.getClass ()
             .getMethod("setRequestedSessionId", String.class)
             .invoke   (request , id);
    } catch ( NoSuchMethodException ex) {
        // Log
    } catch (IllegalAccessException |
           IllegalArgumentException |
          InvocationTargetException ex) {
        // Log
    }

呵呵!

需要注意,必須在目前請求首次呼叫 getSession 之前執行才行,尤其註意上層是否有 Filter 中使用到 Session


2016/05/21 更新實驗結果

以上方法 SessionID 是可以換掉的,但是卻取不出來 Session,因取時還會對 Session 進行驗證,追蹤 Jetty 的源碼發現,設定 Session 物件是在初始化 Request 的時候,如下圖:

此時還沒進行到 Servlet 和 Filter,無從下手,因此看來重設沒那麼簡單。

以上只對 Jetty 做了實測,結果失敗。 Tomcat 沒實驗,看原始碼有 changeSessionId(String) 方法,看邏輯應該是可以的。


2016/05/21 再次更新結果

經過不斷的折騰,用以下程式碼重設 sessionId 成功:

    try {
        Object obj;
        obj = req.getClass ()
           .getMethod("getSessionManager")
           .invoke   (req);
        obj = obj.getClass ()
           .getMethod("getHttpSession" , String.class)
           .invoke   (obj, sid);
        req.getClass ()
           .getMethod("setSession", HttpSession.class)
           .invoke   (req, (HttpSession) obj);
    } catch ( NoSuchMethodException ex ) {
        // Log
    } catch (IllegalAccessException  |
           IllegalArgumentException  |
          InvocationTargetException ex ) {
        // Log
    }

在此之後執行的程式什麼也不用變,可正常使用 request.getSession() 來讀寫 Session, 此方法針對 Jetty 寫的.


2015/05/22 Tomcat 實測更新

吃完早餐無聊,追蹤了下Tomcat 的程式碼,使用Tomcat 7,8 兩個版本,發現其交給用戶Servlet 的Request 物件是一個叫RequestFacade 的代理類,此類僅對HttpServletRequest 介面的方法做了實現,隱藏了他的Request 對象,因此無法呼叫到org.apache.catalina.connector.Request 的setRequestedSessionId 等方法。

看來也只能針對 Jetty 實現此 Hack 了。


結果雖然不太樂觀,且沒準 Jetty 在之後的版本裡也會隱藏那些方法,不過這個實驗過程又對這兩種應用容器有了更進一步的了解。 Cookie 也好,URL Path Parameter 也好,GET/POST 參數也好,只是在請求資料的不同位置攜帶 Session Token 而已,在客戶端對連接做個簡單封裝也許更方便.

Ty80

使用 token 的方式,把 token 放在請求頭裡面。要求前端在請求的時候要帶這個 token

熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板