将含有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外,若是不能够的话,再按我这个思路作改动