Spring WS + Wss4jSecurityInterceptor + MTOM memory

2019-08-14 09:55发布

This seems to be somewhat a longstanding question, and no definitive solution so far: situations where your incoming MTOM messages get inlined to the SOAP message, crashing the application due to memory usage.

I'm creating a file upload webservice with Spring WS (2.1) using Apache Axiom (1.2.13) because the files I receive are big:

<bean id="messageFactory" class="org.springframework.ws.soap.axiom.AxiomSoapMessageFactory">
    <property name="payloadCaching" value="true"/>
    <property name="attachmentCaching" value="true"/>
</bean>

I'm using JAXB (2.2.5) for XML data marshalling, but it inlines attachments, so for endpoints that handle attachments I use SoapMessage directly; not what I would prefer, but acceptable. Up to this point is fine with this setup, and I can upload very big files. The problem is that I also need authentication, for which I'm using Apache WSS4J 1.6.6:

<bean id="wsSecurityInterceptor" class="org.springframework.ws.soap.security.wss4j.Wss4jSecurityInterceptor">
    <property name="validationActions" value="UsernameToken"/>
    <property name="securementActions" value="NoSecurity"/>
</bean>

When the interceptor does the message validation, it also inlines the attachment data to the body of the message, eating lots of memory and generating OutOfMemoryError on reasonably sized messages:

java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOfRange(Arrays.java:3209) ~[na:1.6.0_14]
    at java.lang.String.<init>(String.java:215) ~[na:1.6.0_14]
    at com.sun.org.apache.xerces.internal.xni.XMLString.toString(XMLString.java:185) ~[na:1.6.0_14]
    at com.sun.org.apache.xerces.internal.parsers.AbstractDOMParser.characters(AbstractDOMParser.java:1188) ~[na:1.6.0_14]
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:463) ~[na:1.6.0_14]
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:807) ~[na:1.6.0_14]
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737) ~[na:1.6.0_14]
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:107) ~[na:1.6.0_14]
    at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:225) ~[na:1.6.0_14]
    at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:283) ~[na:1.6.0_14]
    at weblogic.xml.jaxp.RegistryDocumentBuilder.parse(RegistryDocumentBuilder.java:163) ~[weblogic.jar:10.3.2.0]
    at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:124) ~[na:1.6.0_14]
    at org.springframework.ws.soap.axiom.support.AxiomUtils.toDocument(AxiomUtils.java:133) ~[spring-ws-core-2.1.0.RELEASE.jar:na]
    at org.springframework.ws.soap.axiom.AxiomSoapMessage.getDocument(AxiomSoapMessage.java:201) ~[spring-ws-core-2.1.0.RELEASE.jar:na]
    at org.springframework.ws.soap.security.wss4j.Wss4jSecurityInterceptor.validateMessage(Wss4jSecurityInterceptor.java:561) ~[spring-ws-security-2.1.0.RELEASE.jar:na]
    at org.springframework.ws.soap.security.AbstractWsSecurityInterceptor.handleRequest(AbstractWsSecurityInterceptor.java:123) ~[spring-ws-security-2.1.0.RELEASE.jar:na]
    at org.springframework.ws.server.endpoint.interceptor.DelegatingSmartEndpointInterceptor.handleRequest(DelegatingSmartEndpointInterceptor.java:78) ~[spring-ws-core-2.1.0.RELEASE.jar:na]
    at org.springframework.ws.server.MessageDispatcher.dispatch(MessageDispatcher.java:224) ~[spring-ws-core-2.1.0.RELEASE.jar:na]
    at org.springframework.ws.server.MessageDispatcher.receive(MessageDispatcher.java:173) ~[spring-ws-core-2.1.0.RELEASE.jar:na]
    at org.springframework.ws.transport.support.WebServiceMessageReceiverObjectSupport.handleConnection(WebServiceMessageReceiverObjectSupport.java:88) ~[spring-ws-core-2.1.0.RELEASE.jar:na]
    at org.springframework.ws.transport.http.WebServiceMessageReceiverHandlerAdapter.handle(WebServiceMessageReceiverHandlerAdapter.java:59) ~[spring-ws-core-2.1.0.RELEASE.jar:na]
    at org.springframework.ws.transport.http.MessageDispatcherServlet.doService(MessageDispatcherServlet.java:221) ~[spring-ws-core-2.1.0.RELEASE.jar:na]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882) ~[org.springframework.web.servlet-3.1.0.RELEASE.jar:3.1.0.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:789) ~[org.springframework.web.servlet-3.1.0.RELEASE.jar:3.1.0.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:727) ~[javax.servlet_1.0.0.0_2-5.jar:2.5]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:820) ~[javax.servlet_1.0.0.0_2-5.jar:2.5]
    at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:227) ~[weblogic.jar:10.3.2.0]
    at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:125) ~[weblogic.jar:10.3.2.0]
    at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:292) ~[weblogic.jar:10.3.2.0]
    at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:175) ~[weblogic.jar:10.3.2.0]
    at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3591) ~[weblogic.jar:10.3.2.0]
    at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321) ~[com.bea.core.weblogic.security.identity_1.1.2.0.jar:1.1.2.0]

I haven't found a way to fix this undesired inlining so far. I don't want to read and handle the header manually, it would make WSS4J pointless, and my code less flexible to handle future requirements.

This thread suggests fooling the interceptor into using a copy of the message containing only the header, but I couldn't implement it (it is a few years old, the API may be changed). This would probably forbid the use of encrypted and signed messages (as a reply points out), but so far not a requirement for me. This other thread suggests sticking with Axiom 1.2.8, which did nothing, and also setting the validateRequest flag on the Axiom factory to false (this one sounds strange, as it disables security - no error but no security, what would be the point of it?).

So, anybody can help me with a solution to this issue? Fixing JAXB, tricking the WSS4J interceptor, or some other solution? Any help is welcome!

Thanks!

0条回答
登录 后发表回答