記WEBLOGIC部署BUG(WEBSOCKET)
將含有websocket的SSM項目部署在Weblogic上面,遇到websocket報錯如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
java.lang.ClassCastException: org.springframework.session.web.http.SessionReposi
toryFilter$SessionRepositoryRequestWrapper$HttpSessionWrapper cannot be cast to
weblogic.servlet.security.internal.SessionSecurityData
at weblogic.servlet.security.internal.SecurityModule.getCurrentUser(Secu
rityModule.java:197)
at weblogic.websocket.tyrus.TyrusServletFilter.doFilter(TyrusServletFilt
er.java:167)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.ja
va:78)
at com.codahale.metrics.servlet.AbstractInstrumentedFilter.doFilter(Abst
ractInstrumentedFilter.java:104)
at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.ja
va:78)
Truncated. see log file for complete stacktrace
直觀看,是類型轉換錯誤,發生在weblogic的對象中.
可以搜到的類似問題中,都在嘗試將/websocket排除在web.xml中的filter之外,而這邊遇到的項目,這麼做不現實,所以開始分析該bug
思路:
1.DEBUG獲取到出錯的 filterChain,發現weblogic自行追加了一個fitler,叫TyrusServletFilter,錯誤在這個Filter中發生.
2.從weblogic的安裝目錄中找到TyrusServletFilter的jar包,引入到IDEA,準備反編譯看源碼
3.根據上面的報錯,錯誤發生在SecurityModule中的getCurrentUser中,打斷點DEBUG確定到具體行:
上圖是TyrusServletFilter的反編譯代碼,紅線處可看到,進入出錯代碼的條件
具體出錯行,非常明了的強制轉換,轉換了request.getSession的結果
4.在該處進行DEBUG(居然真的能DEBUG),發現正常的時候,getCurrentUser的request參數是一個ServletRequestImpl對象(來自weblogic),而出錯時,request參數是一個SecurityContextHolderAwareRequestWrapper對象,故確定問題是包裝問題(即包裝器的getSession並沒有代理好其內部request的getSession方法)
解決方案:
確定了出錯的包裝類後,要重寫並覆蓋該類,代碼如下:
該包裝類原本並沒有覆蓋getSession方法,這裡添加覆蓋,加入和TyrusServletFilter中相同的判斷邏輯,
如果符合條件,則就地一層一層拆包裝,拆到ServletRequestImpl為止.再調用ServletRequestImpl的getSession返回出結果.
如果不符合條件,不做改變.
這大概是解決該問題的另一套思路了.
我這裡由於使用了SpringSecurity,故要做修改的是SecurityContextHolderAwareRequestWrapper
如果使用了別的filter,那麼可以覆蓋其他的requestWrapper
當然最簡單的方案還是在web.xml中將/websocket排除在所有filter外,如果不可以的話,再按我這個思路做改動
作者: 用戶註冊了一次
原文:https://www.cnblogs.com/user-for-once/p/10307394.html
※如何在前端進行簡訊介面和語音驗證介面的使用
※微服務日誌的七種最佳實踐
TAG:程序員小新人學習 |