Rumah > Soal Jawab > teks badan
我有个项目,希望在 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 里。
来问问有什么简单的方式解决这个问题没?
天蓬老师2017-04-17 17:59:18
搞定了,我查了 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 而已,在客户端对连接做个简单封装也许更方便.