將含有websocket的SSM項目部署在Weblogic上面,遇到websocket報錯以下java
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的對象中.web
能夠搜到的相似問題中,都在嘗試將/websocket排除在web.xml中的filter以外,而這邊遇到的項目,這麼作不現實,因此開始分析該bugspring
思路:websocket
1.DEBUG獲取到出錯的 filterChain,發現weblogic自行追加了一個fitler,叫TyrusServletFilter,錯誤在這個Filter中發生.session
2.從weblogic的安裝目錄中找到TyrusServletFilter的jar包,引入到IDEA,準備反編譯看源碼app
3.根據上面的報錯,錯誤發生在SecurityModule中的getCurrentUser中,打斷點DEBUG肯定到具體行:socket
上圖是TyrusServletFilter的反編譯代碼,紅線處可看到,進入出錯代碼的條件代理
具體出錯行,很是明瞭的強制轉換,轉換了request.getSession的結果xml
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外,若是不能夠的話,再按我這個思路作改動