尝试流式传输/下载时,Spring Security 4关闭与浏览器的连接(Vaadin UI)

时间:2017-04-13 20:14:23

标签: spring-security

我正在升级到Java 8,Spring 4和Spring Security 4(来自Java 7,Spring / Security 3,其中一切正常)。升级后,除了从服务器下载/流式传输到浏览器的能力之外的一切都可以正常工作。

对于UI,我们使用Vaadin。在一个实例中,我在浏览器中创建一个框架,该框架应显示PDF并在输入流中提供application / pdf类型的数据。在其他情况下,流返回浏览器以保存为文件

在Java中调试,我看到一个打开的InputStream,其中包含要在浏览器中下载的数据。数据从输入流中读取并写入response.OutputStream,它也是打开的。但是,当Tomcat尝试将输出流数据写入套接字时,它会抛出您可以在下面看到的异常(Tomcat 8.5在尝试刷新数据时抛出异常,Tomcat 7在尝试刷新数据时抛出异常 - 不同的实现)。似乎已终止与浏览器的连接。只有在使用Spring Security保护应用程序时才会发生这种情况。如果我删除安全性一切正常(它也适用于Spring Security 3)

非常感谢任何解决此问题的帮助!如果我能提供任何其他信息来解释这个问题,请告诉我。

web.xml

<filter>
    <filter-name>MultipartFilter</filter-name>
    <filter-class>org.springframework.web.multipart.support.MultipartFilter</filter-class>
</filter>
<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
    <filter-name>MultipartFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

安全配置:

<context:property-placeholder ignore-resource-not-found="true" location="classpath:CALC.properties" />
<security:global-method-security pre-post-annotations="enabled" secured-annotations="enabled" />

<bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder">
    <constructor-arg value=".." />
</bean>

<security:authentication-manager alias="authenticationManager">
    <security:authentication-provider user-service-ref="${service.calc.security.service}">
        <security:password-encoder ref="passwordEncoder" />
    </security:authentication-provider>
</security:authentication-manager>

<security:http pattern="/VAADIN/**" security="none" />
<security:http pattern="/loggedout*" security="none" />
<security:http auto-config='true' use-expressions="true" realm="Illustration System">
    <security:intercept-url pattern="/**" access="isFullyAuthenticated()" />
    <security:http-basic />
    <security:csrf disabled="true"/>
    <security:anonymous granted-authority="ROLE_USER" />
</security:http>

<bean id="logoutHandler" class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler">
    <property name="invalidateHttpSession" value="true" />
</bean>

堆栈追踪:

org.apache.catalina.connector.ClientAbortException: java.io.IOException: An established connection was aborted by the software in your host machine
    at org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:356) ~[catalina.jar:8.5.13]
    at org.apache.catalina.connector.OutputBuffer.appendByteArray(OutputBuffer.java:778) ~[catalina.jar:8.5.13]
    at org.apache.catalina.connector.OutputBuffer.append(OutputBuffer.java:707) ~[catalina.jar:8.5.13]
    at org.apache.catalina.connector.OutputBuffer.writeBytes(OutputBuffer.java:391) ~[catalina.jar:8.5.13]
    at org.apache.catalina.connector.OutputBuffer.write(OutputBuffer.java:369) ~[catalina.jar:8.5.13]
    at org.apache.catalina.connector.CoyoteOutputStream.write(CoyoteOutputStream.java:96) ~[catalina.jar:8.5.13]
    at org.springframework.security.web.util.OnCommittedResponseWrapper$SaveContextServletOutputStream.write(OnCommittedResponseWrapper.java:639) ~[spring-security-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at com.vaadin.server.DownloadStream.writeResponse(DownloadStream.java:307) ~[vaadin-server-7.7.8.jar:7.7.8]
    at com.vaadin.server.AbstractClientConnector.handleConnectorRequest(AbstractClientConnector.java:682) ~[vaadin-server-7.7.8.jar:7.7.8]
    at com.vaadin.server.ConnectorResourceHandler.handleRequest(ConnectorResourceHandler.java:90) [vaadin-server-7.7.8.jar:7.7.8]
    at com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1422) [vaadin-server-7.7.8.jar:7.7.8]
    at com.vaadin.server.VaadinServlet.service(VaadinServlet.java:380) [vaadin-server-7.7.8.jar:7.7.8]
    at com.calcfocus.webui.util.CalcFocusServlet.service(CalcFocusServlet.java:21) [webui-2.0.0-SNAPSHOT.jar:2.0.0-SNAPSHOT]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) [servlet-api.jar:?]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230) [catalina.jar:8.5.13]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) [catalina.jar:8.5.13]
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) [tomcat-websocket.jar:8.5.13]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) [catalina.jar:8.5.13]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) [catalina.jar:8.5.13]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:317) [spring-security-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:127) [spring-security-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91) [spring-security-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:114) [spring-security-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137) [spring-security-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111) [spring-security-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:170) [spring-security-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) [spring-security-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilterInternal(BasicAuthenticationFilter.java:215) [spring-security-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.5.RELEASE.jar:4.3.5.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter.doFilter(DefaultLoginPageGeneratingFilter.java:177) [spring-security-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:200) [spring-security-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116) [spring-security-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64) [spring-security-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.5.RELEASE.jar:4.3.5.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) [spring-security-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.5.RELEASE.jar:4.3.5.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) [spring-security-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) [spring-security-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214) [spring-security-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177) [spring-security-web-4.2.2.RELEASE.jar:4.2.2.RELEASE]
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346) [spring-web-4.3.5.RELEASE.jar:4.3.5.RELEASE]
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262) [spring-web-4.3.5.RELEASE.jar:4.3.5.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) [catalina.jar:8.5.13]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) [catalina.jar:8.5.13]
    at org.springframework.web.multipart.support.MultipartFilter.doFilterInternal(MultipartFilter.java:122) [spring-web-4.3.5.RELEASE.jar:4.3.5.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.5.RELEASE.jar:4.3.5.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) [catalina.jar:8.5.13]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) [catalina.jar:8.5.13]
    at org.apache.logging.log4j.web.Log4jServletFilter.doFilter(Log4jServletFilter.java:71) [log4j-web-2.3.jar:2.3]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) [catalina.jar:8.5.13]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) [catalina.jar:8.5.13]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) [catalina.jar:8.5.13]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [catalina.jar:8.5.13]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478) [catalina.jar:8.5.13]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [catalina.jar:8.5.13]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80) [catalina.jar:8.5.13]
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:624) [catalina.jar:8.5.13]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [catalina.jar:8.5.13]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:341) [catalina.jar:8.5.13]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799) [tomcat-coyote.jar:8.5.13]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-coyote.jar:8.5.13]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:861) [tomcat-coyote.jar:8.5.13]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455) [tomcat-coyote.jar:8.5.13]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-coyote.jar:8.5.13]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [?:1.8.0_121]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [?:1.8.0_121]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-util.jar:8.5.13]
    at java.lang.Thread.run(Thread.java:745) [?:1.8.0_121]
Caused by: java.io.IOException: An established connection was aborted by the software in your host machine
    at sun.nio.ch.SocketDispatcher.write0(Native Method) ~[?:1.8.0_121]
    at sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:51) ~[?:1.8.0_121]
    at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:93) ~[?:1.8.0_121]
    at sun.nio.ch.IOUtil.write(IOUtil.java:65) ~[?:1.8.0_121]
    at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:471) ~[?:1.8.0_121]
    at org.apache.tomcat.util.net.NioChannel.write(NioChannel.java:134) ~[tomcat-coyote.jar:8.5.13]
    at org.apache.tomcat.util.net.NioBlockingSelector.write(NioBlockingSelector.java:101) ~[tomcat-coyote.jar:8.5.13]
    at org.apache.tomcat.util.net.NioSelectorPool.write(NioSelectorPool.java:157) ~[tomcat-coyote.jar:8.5.13]
    at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.doWrite(NioEndpoint.java:1259) ~[tomcat-coyote.jar:8.5.13]
    at org.apache.tomcat.util.net.SocketWrapperBase.doWrite(SocketWrapperBase.java:670) ~[tomcat-coyote.jar:8.5.13]
    at org.apache.tomcat.util.net.SocketWrapperBase.writeBlocking(SocketWrapperBase.java:450) ~[tomcat-coyote.jar:8.5.13]
    at org.apache.tomcat.util.net.SocketWrapperBase.write(SocketWrapperBase.java:388) ~[tomcat-coyote.jar:8.5.13]
    at org.apache.coyote.http11.Http11OutputBuffer$SocketOutputBuffer.doWrite(Http11OutputBuffer.java:644) ~[tomcat-coyote.jar:8.5.13]
    at org.apache.coyote.http11.filters.ChunkedOutputFilter.doWrite(ChunkedOutputFilter.java:123) ~[tomcat-coyote.jar:8.5.13]
    at org.apache.coyote.http11.Http11OutputBuffer.doWrite(Http11OutputBuffer.java:235) ~[tomcat-coyote.jar:8.5.13]
    at org.apache.coyote.Response.doWrite(Response.java:518) ~[tomcat-coyote.jar:8.5.13]
    at org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:351) ~[catalina.jar:8.5.13]
    ... 79 more

2 个答案:

答案 0 :(得分:2)

在Spring 3到4迁移指南中找到答案

performSegueWithIdentifier:()`

第6.6节迁移标题

作为Spring Security 4.0+安全HTTP响应标头现在默认启用。

标题的存在(以某种方式)阻止了下载流。

建议:通过将csrf和headers标记添加到配置以使其运行来开始迁移,然后尝试了解是否可以禁用这些功能。另外,阅读指南,它可能会节省你一些时间......奇怪的是:-)

<security:http auto-config='true' use-expressions="true" realm="Illustration System">
    <security:intercept-url pattern="/**" access="isFullyAuthenticated()" />
    <security:http-basic />
    <security:csrf disabled="true"/>
    <security:headers disabled="true"/>
</security:http>

答案 1 :(得分:2)

Spring Boot中存在与Spring安全性相同的问题。我无法在HttpServletResponse outputStream中传输视频。用Java配置解决了它。

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class SecurityConfig extends WebSecurityConfigurerAdapter{

   @Override    
   protected void configure(HttpSecurity http) throws Exception {
    http
       .csrf().disable()
       .headers().disable()

       .authorizeRequests()             
            .antMatchers("/").permitAll()           // home page
            .anyRequest().authenticated();
   }

   //... other methods
}