Websockets 后备选项流在 AWS 中不起作用

Websockets fallback option streaming not working in AWS

我们在使回退选项在 AWS 环境中工作时遇到问题。

Setup details and background We have Spring REST web services running in the AWS cloud environment. All services are running under tomcat 8. SSL is terminated at ELB. We are working with a vendor for providing us the AWS services, who added another component(WAF) in front of ELB that is not supporting web socket. So instead of websocket we were testing streaming as a fallback option. We are using spring websocket using sockJS.

回退选项也不起作用,这给了我们以下异常

2015-12-07 18:07:43,859 [http-nio-8080-exec-5] DEBUG - Closing due to transport error for XhrStreamingSockJsSession[id=aahouqlj]
2015-12-07 18:07:43,859 [http-nio-8080-exec-5] DEBUG - Transport error in XhrStreamingSockJsSession[id=aahouqlj]
java.lang.IllegalArgumentException: Async support must be enabled on a servlet and for all filters involved in async request processing. This is done in Java code using the Servlet API or by adding "<async-supported>true</async-supported>" to servlet and filter declarations in web.xml. Also you must use a Servlet 3.0+ container
>---at org.springframework.util.Assert.isTrue(Assert.java:65) ~[spring-core-4.1.7.RELEASE.jar:4.1.7.RELEASE]
>---at org.springframework.http.server.ServletServerHttpAsyncRequestControl.<init>(ServletServerHttpAsyncRequestControl.java:58) ~[spring-web-4.1.7.RELEASE.jar:4.1.7.RELEASE]
>---at org.springframework.http.server.ServletServerHttpRequest.getAsyncRequestControl(ServletServerHttpRequest.java:213) ~[spring-web-4.1.7.RELEASE.jar:4.1.7.RELEASE]
>---at org.springframework.web.socket.sockjs.transport.session.AbstractHttpSockJsSession.handleInitialRequest(AbstractHttpSockJsSession.java:202) [spring-websocket-4.1.7.RELEASE.jar:4.1.7.RELEASE]
>---at org.springframework.web.socket.sockjs.transport.handler.AbstractHttpSendingTransportHandler.handleRequestInternal(AbstractHttpSendingTransportHandler.java:68) [spring-websocket-4.1.7.RELEASE.jar:4.1.7.RELEASE]
>---at org.springframework.web.socket.sockjs.transport.handler.AbstractHttpSendingTransportHandler.handleRequest(AbstractHttpSendingTransportHandler.java:58) [spring-websocket-4.1.7.RELEASE.jar:4.1.7.RELEASE]
>---at org.springframework.web.socket.sockjs.transport.TransportHandlingSockJsService.handleTransportRequest(TransportHandlingSockJsService.java:272) [spring-websocket-4.1.7.RELEASE.jar:4.1.7.RELEASE]
>---at org.springframework.web.socket.sockjs.support.AbstractSockJsService.handleRequest(AbstractSockJsService.java:407) [spring-websocket-4.1.7.RELEASE.jar:4.1.7.RELEASE]
>---at org.springframework.web.socket.sockjs.support.SockJsHttpRequestHandler.handleRequest(SockJsHttpRequestHandler.java:90) [spring-websocket-4.1.7.RELEASE.jar:4.1.7.RELEASE]
>---at org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter.handle(HttpRequestHandlerAdapter.java:51) [spring-webmvc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
>---at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959) [spring-webmvc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
>---at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893) [spring-webmvc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
>---at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:967) [spring-webmvc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
>---at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:869) [spring-webmvc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
>---at javax.servlet.http.HttpServlet.service(HttpServlet.java:648) [servlet-api.jar:?]
>---at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:843) [spring-webmvc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
>---at javax.servlet.http.HttpServlet.service(HttpServlet.java:729) [servlet-api.jar:?]
>---at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291) [catalina.jar:8.0.23]
>---at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) [catalina.jar:8.0.23]
>---at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) [tomcat-websocket.jar:8.0.23]
>---at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) [catalina.jar:8.0.23]
>---at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) [catalina.jar:8.0.23]
>---at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) [spring-security-web-3.2.5.RELEASE.jar:3.2.5.RELEASE]
>---at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118) [spring-security-web-3.2.5.RELEASE.jar:3.2.5.RELEASE]
>---at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84) [spring-security-web-3.2.5.RELEASE.jar:3.2.5.RELEASE]
>---at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.5.RELEASE.jar:3.2.5.RELEASE]
>---at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113) [spring-security-web-3.2.5.RELEASE.jar:3.2.5.RELEASE]
>---at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.5.RELEASE.jar:3.2.5.RELEASE]
>---at com.company.iac.common.security.AuthenticationFilter.successfulAuthentication(AuthenticationFilter.java:184) [iac-common-0.1.jar:0.1]
>---at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:235) [spring-security-web-3.2.5.RELEASE.jar:3.2.5.RELEASE]
>---at com.company.iac.common.security.AuthenticationFilter.doFilter(AuthenticationFilter.java:132) [iac-common-0.1.jar:0.1]
>---at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.5.RELEASE.jar:3.2.5.RELEASE]
>---at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103) [spring-security-web-3.2.5.RELEASE.jar:3.2.5.RELEASE]
>---at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.5.RELEASE.jar:3.2.5.RELEASE]
>---at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:154) [spring-security-web-3.2.5.RELEASE.jar:3.2.5.RELEASE]
>---at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.5.RELEASE.jar:3.2.5.RELEASE]
>---at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45) [spring-security-web-3.2.5.RELEASE.jar:3.2.5.RELEASE]
-at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.5.RELEASE.jar:3.2.5.RELEASE]
>---at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:57) [spring-security-web-3.2.5.RELEASE.jar:3.2.5.RELEASE]
>---at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.1.7.RELEASE.jar:4.1.7.RELEASE]
>---at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.5.RELEASE.jar:3.2.5.RELEASE]
>---at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87) [spring-security-web-3.2.5.RELEASE.jar:3.2.5.RELEASE]
>---at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.5.RELEASE.jar:3.2.5.RELEASE]
>---at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50) [spring-security-web-3.2.5.RELEASE.jar:3.2.5.RELEASE]
>---at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.1.7.RELEASE.jar:4.1.7.RELEASE]
>---at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [spring-security-web-3.2.5.RELEASE.jar:3.2.5.RELEASE]
>---at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192) [spring-security-web-3.2.5.RELEASE.jar:3.2.5.RELEASE]
>---at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160) [spring-security-web-3.2.5.RELEASE.jar:3.2.5.RELEASE]
>---at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344) [spring-web-4.1.7.RELEASE.jar:4.1.7.RELEASE]
>---at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261) [spring-web-4.1.7.RELEASE.jar:4.1.7.RELEASE]
>---at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) [catalina.jar:8.0.23]
>---at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) [catalina.jar:8.0.23]
>---at com.company.iac.common.filter.CloudCORSFilter.doFilter(CloudCORSFilter.java:87) [iac-common-0.1.jar:0.1]
>---at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) [catalina.jar:8.0.23]
>---at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) [catalina.jar:8.0.23]
>---at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219) [catalina.jar:8.0.23]
>---at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) [catalina.jar:8.0.23]
>---at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) [catalina.jar:8.0.23]
>---at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142) [catalina.jar:8.0.23]
>---at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) [catalina.jar:8.0.23]
>---at org.apache.catalina.valves.rewrite.RewriteValve.invoke(RewriteValve.java:262) [catalina.jar:8.0.23]
>---at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:617) [catalina.jar:8.0.23]
>---at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) [catalina.jar:8.0.23]
>---at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518) [catalina.jar:8.0.23]
>---at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091) [tomcat-coyote.jar:8.0.23]
>---at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:668) [tomcat-coyote.jar:8.0.23]
>---at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1521) [tomcat-coyote.jar:8.0.23]
>---at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1478) [tomcat-coyote.jar:8.0.23]
>---at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [?:1.8.0_45]
>---at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [?:1.8.0_45]
>---at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-util.jar:8.0.23]
>---at java.lang.Thread.run(Thread.java:745) [?:1.8.0_45]
2015-12-07 18:07:43,866 [http-nio-8080-exec-5] DEBUG - Resolving exception from handler [org.springframework.web.socket.sockjs.support.SockJsHttpRequestHandler@2cc2e2a8]: org.springframework.web.socket.sockjs.SockJsException: Uncaught failure in SockJS request, uri=https://devstaging.pr.apps.company.com:443/events/pr/664/aahouqlj/xhr_streaming?t=1449511663834; nested exception is org.springframework.web.socket.sockjs.SockJsTransportFailureException: Failed to open session; nested exception is java.lang.IllegalArgumentException: Async support must be enabled on a servlet and for all filters involved in async request processing. This is done in Java code using the Servlet API or by adding "<async-supported>true</async-supported>" to servlet and filter declarations in web.xml. Also you must use a Servlet 3.0+ container
2015-12-07 18:07:43,866 [http-nio-8080-exec-5] DEBUG - Resolving exception from handler [org.springframework.web.socket.sockjs.support.SockJsHttpRequestHandler@2cc2e2a8]: org.springframework.web.socket.sockjs.SockJsException: Uncaught failure in SockJS request, uri=https://devstaging.pr.apps.company.com:443/events/pr/664/aahouqlj/xhr_streaming?t=1449511663834; nested exception is org.springframework.web.socket.sockjs.SockJsTransportFailureException: Failed to open session; nested exception is java.lang.IllegalArgumentException: Async support must be enabled on a servlet and for all filters involved in async request processing. This is done in Java code using the Servlet API or by adding "<async-supported>true</async-supported>" to servlet and filter declarations in web.xml. Also you must use a Servlet 3.0+ container
Caused by: org.springframework.web.socket.sockjs.SockJsTransportFailureException: Failed to open session; nested exception is java.lang.IllegalArgumentException: Async support must be enabled on a servlet and for all filters involved in async request processing. This is done in Java code using the Servlet API or by adding "<async-supported>true</async-supported>" to servlet and filter declarations in web.xml. Also you must use a Servlet 3.0+ container
>---at org.springframework.web.socket.sockjs.transport.session.AbstractHttpSockJsSession.handleInitialRequest(AbstractHttpSockJsSession.java:220) ~[spring-websocket-4.1.7.RELEASE.jar:4.1.7.RELEASE]
>---at org.springframework.web.socket.sockjs.transport.handler.AbstractHttpSendingTransportHandler.handleRequestInternal(AbstractHttpSendingTransportHandler.java:68) ~[spring-websocket-4.1.7.RELEASE.jar:4.1.7.RELEASE]
>---at org.springframework.web.socket.sockjs.transport.handler.AbstractHttpSendingTransportHandler.handleRequest(AbstractHttpSendingTransportHandler.java:58) ~[spring-websocket-4.1.7.RELEASE.jar:4.1.7.RELEASE]
>---at org.springframework.web.socket.sockjs.transport.TransportHandlingSockJsService.handleTransportRequest(TransportHandlingSockJsService.java:272) ~[spring-websocket-4.1.7.RELEASE.jar:4.1.7.RELEASE]
>---at org.springframework.web.socket.sockjs.support.AbstractSockJsService.handleRequest(AbstractSockJsService.java:407) ~[spring-websocket-4.1.7.RELEASE.jar:4.1.7.RELEASE]
>---at org.springframework.web.socket.sockjs.support.SockJsHttpRequestHandler.handleRequest(SockJsHttpRequestHandler.java:90) ~[spring-websocket-4.1.7.RELEASE.jar:4.1.7.RELEASE]
>---... 63 more

我们正在使用 spring 版本 4.1.7。我可以看到 filterchain 和 servlet 默认启用了异步支持。 spring 安全配置如下所示

   protected void configure(HttpSecurity http) throws Exception {

        http.csrf().disable().logout().disable().anonymous().disable().authorizeRequests()
        .anyRequest().permitAll().and().addFilterBefore(authenticationFilter() , ExceptionTranslationFilter.class).
        sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

auth 过滤器扩展了 AbstractAuthenticationProcessingFilter

public class AuthenticationFilter 扩展了 AbstractAuthenticationProcessingFilter {

    public AuthenticationFilter(AuthenticationManager authenticationManager) {
        super(new DummyRequestMatcher());
        this.setAuthenticationManager(authenticationManager);
    }

authFilter 是否必须启用异步支持?如果是,那么我还没有找到这样做的方法。我假设 springsecurityfilters 默认将异步标志设置为 true。

你还看到我遗漏了什么吗?

存在多个问题。 第一个问题是我们介绍的阀门。它充当过滤器,因此我们需要将异步标志设置为 true()。 Tomcat 文档没有谈论它,但从 Whosebug 找到了这个 valve is also a filter 第二个问题是来自 spring 安全性的身份验证对象。我们错过了实现 equals 方法,因此在连接(xhr_send)之前调用失败并出现 404 错误。