From e989f33fc7e71b27f549c558f2897aa19ca00667 Mon Sep 17 00:00:00 2001 From: Jim Ma Date: Mon, 21 Oct 2024 20:13:29 +0800 Subject: [PATCH 1/3] [JBWS-4430]:Sever throws IllegalStateException when call a handler with the CDI bean invocation --- .../stack/cxf/JAXPDelegateClassLoader.java | 3 + .../stack/cxf/configuration/BusHolder.java | 2 + .../interceptor/HandlerAuthInterceptor.java | 104 ++++++++++++++---- .../cxf/interceptor/SecurityActions.java | 79 +++++++++++++ modules/testsuite/cxf-tests/pom.xml | 5 + .../ws/jaxws/cxf/jbws4430/DelegateBean.java | 27 +++++ .../test/ws/jaxws/cxf/jbws4430/EmptyBean.java | 25 +++++ .../test/ws/jaxws/cxf/jbws4430/Hello.java | 26 +++++ .../test/ws/jaxws/cxf/jbws4430/HelloBean.java | 34 ++++++ .../jaxws/cxf/jbws4430/JBWS4430TestCase.java | 73 ++++++++++++ .../ws/jaxws/cxf/jbws4430/LoggingHandler.java | 52 +++++++++ .../jaxws/cxf/jbws4430/WEB-INF/web.xml | 17 +++ .../cxf/jbws4430/WEB-INF/wsdl/HelloWorld.wsdl | 56 ++++++++++ .../resources/jaxws/cxf/jbws4430/handlers.xml | 8 ++ pom.xml | 6 + 15 files changed, 498 insertions(+), 19 deletions(-) create mode 100644 modules/server/src/main/java/org/jboss/wsf/stack/cxf/interceptor/SecurityActions.java create mode 100644 modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/DelegateBean.java create mode 100644 modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/EmptyBean.java create mode 100644 modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/Hello.java create mode 100644 modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/HelloBean.java create mode 100644 modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/JBWS4430TestCase.java create mode 100644 modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/LoggingHandler.java create mode 100644 modules/testsuite/cxf-tests/src/test/resources/jaxws/cxf/jbws4430/WEB-INF/web.xml create mode 100644 modules/testsuite/cxf-tests/src/test/resources/jaxws/cxf/jbws4430/WEB-INF/wsdl/HelloWorld.wsdl create mode 100644 modules/testsuite/cxf-tests/src/test/resources/jaxws/cxf/jbws4430/handlers.xml diff --git a/modules/server/src/main/java/org/jboss/wsf/stack/cxf/JAXPDelegateClassLoader.java b/modules/server/src/main/java/org/jboss/wsf/stack/cxf/JAXPDelegateClassLoader.java index 4149297b9..59d56ef08 100644 --- a/modules/server/src/main/java/org/jboss/wsf/stack/cxf/JAXPDelegateClassLoader.java +++ b/modules/server/src/main/java/org/jboss/wsf/stack/cxf/JAXPDelegateClassLoader.java @@ -104,4 +104,7 @@ public InputStream getResourceAsStream(final String name) } return (is == null && !skipSps.contains(name)) ? delegate.getResourceAsStream(name) : is; } + public ClassLoader getDelegate() { + return this.delegate; + } } diff --git a/modules/server/src/main/java/org/jboss/wsf/stack/cxf/configuration/BusHolder.java b/modules/server/src/main/java/org/jboss/wsf/stack/cxf/configuration/BusHolder.java index 47843d639..ebd210db8 100644 --- a/modules/server/src/main/java/org/jboss/wsf/stack/cxf/configuration/BusHolder.java +++ b/modules/server/src/main/java/org/jboss/wsf/stack/cxf/configuration/BusHolder.java @@ -367,6 +367,8 @@ protected void setInterceptors(Bus bus, Deployment dep, Map prop final String p = (props != null) ? props.get(Constants.JBWS_CXF_DISABLE_HANDLER_AUTH_CHECKS) : null; if ((p == null || (!"true".equalsIgnoreCase(p) && !"1".equalsIgnoreCase(p))) && !Boolean.getBoolean(Constants.JBWS_CXF_DISABLE_HANDLER_AUTH_CHECKS)) { bus.getInInterceptors().add(new HandlerAuthInterceptor()); + } else { + bus.getInInterceptors().add(new HandlerAuthInterceptor(true)); } final SOAPAddressRewriteMetadata sarm = dep.getAttachment(SOAPAddressRewriteMetadata.class); diff --git a/modules/server/src/main/java/org/jboss/wsf/stack/cxf/interceptor/HandlerAuthInterceptor.java b/modules/server/src/main/java/org/jboss/wsf/stack/cxf/interceptor/HandlerAuthInterceptor.java index 40bc62a05..0ac55f806 100644 --- a/modules/server/src/main/java/org/jboss/wsf/stack/cxf/interceptor/HandlerAuthInterceptor.java +++ b/modules/server/src/main/java/org/jboss/wsf/stack/cxf/interceptor/HandlerAuthInterceptor.java @@ -44,23 +44,41 @@ import org.jboss.wsf.spi.deployment.Endpoint; import org.jboss.wsf.spi.security.EJBMethodSecurityAttribute; import org.jboss.wsf.spi.security.EJBMethodSecurityAttributeProvider; +import org.jboss.wsf.stack.cxf.JAXPDelegateClassLoader; /** * Interceptor which checks the current principal is authorized to * call a given handler - * + * * @author alessio.soldano@jboss.com * @since 23-Sep-2013 */ public class HandlerAuthInterceptor extends AbstractPhaseInterceptor { private static final String KEY = HandlerAuthInterceptor.class.getName() + ".SECURITY_EXCEPTION"; - + + private final boolean skip; public HandlerAuthInterceptor() { super(Phase.PRE_PROTOCOL_FRONTEND); addBefore(SOAPHandlerInterceptor.class.getName()); addBefore(LogicalHandlerInInterceptor.class.getName()); + skip = false; + } + /** + * Create a {@code HandlerAuthInterceptor} that can optionally skip authentication. + * When the authentication is skipped, it added a customized {@code JBossWSHandlerChainInvoker} + * which set the correct TCCL to allow the handler to access CDI + * Please see + * This interceptor will be added to CXF interceptor chain + * @param skipAuth a boolean flag indicating whether to skip authentication. + **/ + public HandlerAuthInterceptor(boolean skipAuth) + { + super(Phase.PRE_PROTOCOL_FRONTEND); + addBefore(SOAPHandlerInterceptor.class.getName()); + addBefore(LogicalHandlerInInterceptor.class.getName()); + skip = skipAuth; } @Override @@ -71,61 +89,110 @@ public void handleMessage(Message message) throws Fault if (null == invoker) { final org.apache.cxf.endpoint.Endpoint endpoint = ex.getEndpoint(); - if (endpoint instanceof JaxWsEndpointImpl) { // JAXWS handlers are not assigned to different endpoint types + if (endpoint instanceof JaxWsEndpointImpl) { // JAXWS handlers are not assigned to different endpoint types final JaxWsEndpointImpl ep = (JaxWsEndpointImpl)endpoint; @SuppressWarnings("rawtypes") final List handlerChain = ep.getJaxwsBinding().getHandlerChain(); if (handlerChain != null && !handlerChain.isEmpty()) { //save - invoker = new JBossWSHandlerChainInvoker(handlerChain, isOutbound(message, ex)); + invoker = new JBossWSHandlerChainInvoker(handlerChain, isOutbound(message, ex), skip); ex.put(HandlerChainInvoker.class, invoker); } } } } - + private boolean isOutbound(Message message, Exchange ex) { return message == ex.getOutMessage() - || message == ex.getOutFaultMessage(); + || message == ex.getOutFaultMessage(); } - + private static class JBossWSHandlerChainInvoker extends HandlerChainInvoker { + private final boolean skip; public JBossWSHandlerChainInvoker(@SuppressWarnings("rawtypes") List hc, boolean isOutbound) { super(hc, isOutbound); + skip = false; + } + + public JBossWSHandlerChainInvoker(@SuppressWarnings("rawtypes") List hc, boolean isOutbound, boolean skipAuth) + { + super(hc, isOutbound); + skip = skipAuth; } @Override public boolean invokeLogicalHandlers(boolean requestor, LogicalMessageContext context) { - checkAuthorization(context); - return super.invokeLogicalHandlers(requestor, context); + if (!skip) { + checkAuthorization(context); + } + ClassLoader original = SecurityActions.getContextClassLoader(); + try { + if (original instanceof JAXPDelegateClassLoader) { + JAXPDelegateClassLoader jaxpLoader = (JAXPDelegateClassLoader)original; + SecurityActions.setContextClassLoader(jaxpLoader.getDelegate()); + } + return super.invokeLogicalHandlers(requestor, context); + } finally { + SecurityActions.setContextClassLoader(original); + } } @Override public boolean invokeProtocolHandlers(boolean requestor, MessageContext context) { - checkAuthorization(context); - return super.invokeProtocolHandlers(requestor, context); + if (!skip) { + checkAuthorization(context); + } + ClassLoader original = SecurityActions.getContextClassLoader(); + try { + if (original instanceof JAXPDelegateClassLoader) { + JAXPDelegateClassLoader jaxpLoader = (JAXPDelegateClassLoader)original; + SecurityActions.setContextClassLoader(jaxpLoader.getDelegate()); + } + return super.invokeProtocolHandlers(requestor, context); + } finally { + SecurityActions.setContextClassLoader(original); + } } - + @Override public boolean invokeLogicalHandlersHandleFault(boolean requestor, LogicalMessageContext context) { - if (context.containsKey(KEY)) { + + if (!skip && context.containsKey(KEY)) { return true; } - return super.invokeLogicalHandlersHandleFault(requestor, context); + ClassLoader original = SecurityActions.getContextClassLoader(); + try { + if (original instanceof JAXPDelegateClassLoader) { + JAXPDelegateClassLoader jaxpLoader = (JAXPDelegateClassLoader)original; + SecurityActions.setContextClassLoader(jaxpLoader.getDelegate()); + } + return super.invokeLogicalHandlersHandleFault(requestor, context); + } finally { + SecurityActions.setContextClassLoader(original); + } } @Override public boolean invokeProtocolHandlersHandleFault(boolean requestor, MessageContext context) { - if (context.containsKey(KEY)) { + if (!skip && context.containsKey(KEY)) { return true; } - return super.invokeProtocolHandlersHandleFault(requestor, context); + ClassLoader original = SecurityActions.getContextClassLoader(); + try { + if (original instanceof JAXPDelegateClassLoader) { + JAXPDelegateClassLoader jaxpLoader = (JAXPDelegateClassLoader)original; + SecurityActions.setContextClassLoader(jaxpLoader.getDelegate()); + } + return super.invokeProtocolHandlersHandleFault(requestor, context); + } finally { + SecurityActions.setContextClassLoader(original); + } } protected void checkAuthorization(MessageContext ctx) @@ -138,7 +205,7 @@ protected void checkAuthorization(MessageContext ctx) Exchange exchange = message.getExchange(); Endpoint ep = exchange.get(Endpoint.class); EJBMethodSecurityAttributeProvider attributeProvider = ep - .getAttachment(EJBMethodSecurityAttributeProvider.class); + .getAttachment(EJBMethodSecurityAttributeProvider.class); if (attributeProvider != null) //ejb endpoints only can be associated with this... { SecurityContext secCtx = message.get(SecurityContext.class); @@ -174,5 +241,4 @@ protected void checkAuthorization(MessageContext ctx) } } } - -} +} \ No newline at end of file diff --git a/modules/server/src/main/java/org/jboss/wsf/stack/cxf/interceptor/SecurityActions.java b/modules/server/src/main/java/org/jboss/wsf/stack/cxf/interceptor/SecurityActions.java new file mode 100644 index 000000000..e25d2e6c6 --- /dev/null +++ b/modules/server/src/main/java/org/jboss/wsf/stack/cxf/interceptor/SecurityActions.java @@ -0,0 +1,79 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jboss.wsf.stack.cxf.interceptor; + +import java.security.AccessController; +import java.security.PrivilegedAction; +import org.jboss.wsf.stack.cxf.JAXPDelegateClassLoader; + +/** + * + * @author alessio.soldano@jboss.com + * @since 17-Feb-2010 + * + */ +class SecurityActions +{ + /** + * Get context classloader. + * + * @return the current context classloader + */ + static ClassLoader getContextClassLoader() + { + SecurityManager sm = System.getSecurityManager(); + if (sm == null) + { + return Thread.currentThread().getContextClassLoader(); + } + else + { + return AccessController.doPrivileged(new PrivilegedAction() { + public ClassLoader run() + { + return Thread.currentThread().getContextClassLoader(); + } + }); + } + } + + /** + * Set context classloader. + * + * @param classLoader the classloader + */ + static void setContextClassLoader(final ClassLoader classLoader) + { + if (System.getSecurityManager() == null) + { + Thread.currentThread().setContextClassLoader(classLoader); + } + else + { + AccessController.doPrivileged(new PrivilegedAction() + { + public Object run() + { + Thread.currentThread().setContextClassLoader(classLoader); + return null; + } + }); + } + } +} diff --git a/modules/testsuite/cxf-tests/pom.xml b/modules/testsuite/cxf-tests/pom.xml index 0ef5d5e2e..e9f9e3183 100644 --- a/modules/testsuite/cxf-tests/pom.xml +++ b/modules/testsuite/cxf-tests/pom.xml @@ -106,6 +106,11 @@ cxf-rt-features-throttling test + + jakarta.enterprise + jakarta.enterprise.cdi-api + test + diff --git a/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/DelegateBean.java b/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/DelegateBean.java new file mode 100644 index 000000000..c4bca1c08 --- /dev/null +++ b/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/DelegateBean.java @@ -0,0 +1,27 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jboss.test.ws.jaxws.cxf.jbws4430; + +import jakarta.enterprise.context.Dependent; +import jakarta.enterprise.inject.spi.CDI; + +@Dependent +public class DelegateBean { + EmptyBean logic = CDI.current().select(EmptyBean.class).get(); +} \ No newline at end of file diff --git a/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/EmptyBean.java b/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/EmptyBean.java new file mode 100644 index 000000000..2b31e29d0 --- /dev/null +++ b/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/EmptyBean.java @@ -0,0 +1,25 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jboss.test.ws.jaxws.cxf.jbws4430; + +import jakarta.enterprise.context.Dependent; + +@Dependent +public class EmptyBean { +} diff --git a/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/Hello.java b/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/Hello.java new file mode 100644 index 000000000..e7c6dfc0c --- /dev/null +++ b/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/Hello.java @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jboss.test.ws.jaxws.cxf.jbws4430; + +@jakarta.jws.WebService(wsdlLocation = "WEB-INF/wsdl/HelloWorld.wsdl") +public interface Hello { + + @jakarta.jws.WebMethod + public String hello(String name); +} diff --git a/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/HelloBean.java b/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/HelloBean.java new file mode 100644 index 000000000..a3f657ad3 --- /dev/null +++ b/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/HelloBean.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jboss.test.ws.jaxws.cxf.jbws4430; + +import jakarta.jws.HandlerChain; + +@jakarta.jws.WebService(targetNamespace = "http://test.ws.jboss.org/", + wsdlLocation = "WEB-INF/wsdl/HelloWorld.wsdl") +@HandlerChain(file = "/handlers.xml") +public class HelloBean { + public HelloBean() { + } + + @jakarta.jws.WebMethod + public String hello(String name) { + return "Hello " + name; + } +} diff --git a/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/JBWS4430TestCase.java b/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/JBWS4430TestCase.java new file mode 100644 index 000000000..c14868ec5 --- /dev/null +++ b/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/JBWS4430TestCase.java @@ -0,0 +1,73 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jboss.test.ws.jaxws.cxf.jbws4430; + +import jakarta.xml.ws.Service; +import java.io.File; +import java.net.URL; +import javax.xml.namespace.QName; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.container.test.api.RunAsClient; +import org.jboss.arquillian.junit5.ArquillianExtension; +import org.jboss.arquillian.test.api.ArquillianResource; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.FileAsset; +import org.jboss.shrinkwrap.api.asset.StringAsset; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.jboss.wsf.test.JBossWSTest; +import org.jboss.wsf.test.JBossWSTestHelper; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +@ExtendWith(ArquillianExtension.class) +public class JBWS4430TestCase extends JBossWSTest { + private static final String DEP = "jaxws-cxf-jbws4430"; + + @ArquillianResource + private URL baseURL; + + @Deployment(name = DEP, testable = false) + public static WebArchive createDeployment() { + WebArchive archive = ShrinkWrap.create(WebArchive.class, DEP + ".war"); + archive.setManifest(new StringAsset("Manifest-Version: 1.0\n" + + "Dependencies: org.apache.cxf\n")) + .addClasses(HelloBean.class, DelegateBean.class, EmptyBean.class, LoggingHandler.class) + .addAsWebInfResource(new File(JBossWSTestHelper.getTestResourcesDir() + "/jaxws/cxf/jbws4430/WEB-INF/wsdl/HelloWorld.wsdl"), "wsdl/HelloWorld.wsdl") + .add(new FileAsset(new File(JBossWSTestHelper.getTestResourcesDir() + "/jaxws/cxf/jbws4430/handlers.xml")), "WEB-INF/classes/handlers.xml") + .setWebXML(new File(JBossWSTestHelper.getTestResourcesDir() + "/jaxws/cxf/jbws4430/WEB-INF/web.xml")); + return archive; + } + + @Test + @RunAsClient + public void testWS() throws Exception { + QName serviceName = new QName("http://test.ws.jboss.org/", "HelloBeanService"); + QName portName = new QName("http://test.ws.jboss.org/", "HelloBeanPort"); + + URL wsdlURL = new URL(baseURL + "?wsdl"); + + Service service = Service.create(wsdlURL, serviceName); + Hello proxy = (Hello) service.getPort(portName, Hello.class); + Assertions.assertEquals("Hello jbossws", proxy.hello("jbossws")); + + } + + +} diff --git a/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/LoggingHandler.java b/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/LoggingHandler.java new file mode 100644 index 000000000..2e36558fc --- /dev/null +++ b/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/LoggingHandler.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jboss.test.ws.jaxws.cxf.jbws4430; + +import jakarta.xml.ws.handler.MessageContext; +import jakarta.xml.ws.handler.soap.SOAPHandler; +import jakarta.xml.ws.handler.soap.SOAPMessageContext; +import java.util.Collections; +import java.util.Set; +import javax.xml.namespace.QName; + +public class LoggingHandler implements SOAPHandler { + @Override + public boolean handleMessage(SOAPMessageContext soapMessageContext) { + boolean isOutBound = (boolean) soapMessageContext.get(SOAPMessageContext.MESSAGE_OUTBOUND_PROPERTY); + if (isOutBound) { + new DelegateBean(); + } + return true; + } + + @Override + public Set getHeaders() { + return Collections.emptySet(); + } + + @Override + public boolean handleFault(SOAPMessageContext soapMessageContext) { + return true; + } + + @Override + public void close(MessageContext messageContext) { + // no-operation + } +} diff --git a/modules/testsuite/cxf-tests/src/test/resources/jaxws/cxf/jbws4430/WEB-INF/web.xml b/modules/testsuite/cxf-tests/src/test/resources/jaxws/cxf/jbws4430/WEB-INF/web.xml new file mode 100644 index 000000000..58dc9d622 --- /dev/null +++ b/modules/testsuite/cxf-tests/src/test/resources/jaxws/cxf/jbws4430/WEB-INF/web.xml @@ -0,0 +1,17 @@ + + + + + + HelloBean + org.jboss.test.ws.jaxws.cxf.jbws4430.HelloBean + + + + HelloBean + /* + + diff --git a/modules/testsuite/cxf-tests/src/test/resources/jaxws/cxf/jbws4430/WEB-INF/wsdl/HelloWorld.wsdl b/modules/testsuite/cxf-tests/src/test/resources/jaxws/cxf/jbws4430/WEB-INF/wsdl/HelloWorld.wsdl new file mode 100644 index 000000000..e607a1fb5 --- /dev/null +++ b/modules/testsuite/cxf-tests/src/test/resources/jaxws/cxf/jbws4430/WEB-INF/wsdl/HelloWorld.wsdl @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/testsuite/cxf-tests/src/test/resources/jaxws/cxf/jbws4430/handlers.xml b/modules/testsuite/cxf-tests/src/test/resources/jaxws/cxf/jbws4430/handlers.xml new file mode 100644 index 000000000..84475b9bf --- /dev/null +++ b/modules/testsuite/cxf-tests/src/test/resources/jaxws/cxf/jbws4430/handlers.xml @@ -0,0 +1,8 @@ + + + + + org.jboss.test.ws.jaxws.cxf.jbws4430.LoggingHandler + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index a3efeefed..9b31d8dff 100644 --- a/pom.xml +++ b/pom.xml @@ -126,6 +126,7 @@ 2.1.3 2.4.0.Final + 4.1.0 3.0.4.Final 5.0.29.Final 32.0.1.Final @@ -1056,6 +1057,11 @@ ${testcontainer.version} test + + jakarta.enterprise + jakarta.enterprise.cdi-api + ${jakarta.enterprise.cdi-api.version} + From 68f133469c9d87d73cdc19f8bc1648e4fd676e70 Mon Sep 17 00:00:00 2001 From: Jim Ma Date: Thu, 24 Oct 2024 16:02:55 +0800 Subject: [PATCH 2/3] [JBWS-4430]:Fix IllegalStateException in CXF interceptor when it tries to access CDI bean --- .../AbstractTCCLPhaseInterceptor.java | 54 +++++++++++++++++++ .../jaxws/cxf/jbws4430/CDIOutInterceptor.java | 37 +++++++++++++ .../test/ws/jaxws/cxf/jbws4430/HelloBean.java | 2 + .../jaxws/cxf/jbws4430/JBWS4430TestCase.java | 4 +- 4 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 modules/server/src/main/java/org/jboss/wsf/stack/cxf/interceptor/AbstractTCCLPhaseInterceptor.java create mode 100644 modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/CDIOutInterceptor.java diff --git a/modules/server/src/main/java/org/jboss/wsf/stack/cxf/interceptor/AbstractTCCLPhaseInterceptor.java b/modules/server/src/main/java/org/jboss/wsf/stack/cxf/interceptor/AbstractTCCLPhaseInterceptor.java new file mode 100644 index 000000000..e62e3a66c --- /dev/null +++ b/modules/server/src/main/java/org/jboss/wsf/stack/cxf/interceptor/AbstractTCCLPhaseInterceptor.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jboss.wsf.stack.cxf.interceptor; + +import org.apache.cxf.common.classloader.ClassLoaderUtils; +import org.apache.cxf.interceptor.Fault; +import org.apache.cxf.message.Message; +import org.apache.cxf.phase.AbstractPhaseInterceptor; + +public abstract class AbstractTCCLPhaseInterceptor extends AbstractPhaseInterceptor { + public AbstractTCCLPhaseInterceptor(String phase) { + super(null, phase, false); + } + + public AbstractTCCLPhaseInterceptor(String i, String p) { + super(i, p, false); + } + + public AbstractTCCLPhaseInterceptor(String phase, boolean uniqueId) { + super(null, phase, uniqueId); + } + + public AbstractTCCLPhaseInterceptor(String i, String p, boolean uniqueId) { + super(i,p, uniqueId); + } + + @Override + public void handleMessage(T message) throws Fault { + ClassLoaderUtils.ClassLoaderHolder origLoader = null; + try { + origLoader = ClassLoaderUtils.setThreadContextClassloader(this.getClass().getClassLoader()); + handleMessageWithTCCL(message); + } finally { + origLoader.reset(); + } + } + public abstract void handleMessageWithTCCL(T message) throws Fault; +} diff --git a/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/CDIOutInterceptor.java b/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/CDIOutInterceptor.java new file mode 100644 index 000000000..41e356799 --- /dev/null +++ b/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/CDIOutInterceptor.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jboss.test.ws.jaxws.cxf.jbws4430; +import org.apache.cxf.interceptor.Fault; +import org.apache.cxf.message.Message; +import org.apache.cxf.message.MessageUtils; +import org.apache.cxf.phase.Phase; +import org.jboss.wsf.stack.cxf.interceptor.AbstractTCCLPhaseInterceptor; + +public class CDIOutInterceptor extends AbstractTCCLPhaseInterceptor { + public CDIOutInterceptor() { + super(Phase.PRE_STREAM); + } + + @Override + public void handleMessageWithTCCL(Message message) throws Fault { + if (!MessageUtils.isRequestor(message)) { + DelegateBean bean = new DelegateBean(); + } + } +} diff --git a/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/HelloBean.java b/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/HelloBean.java index a3f657ad3..ed1ca7aa3 100644 --- a/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/HelloBean.java +++ b/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/HelloBean.java @@ -19,10 +19,12 @@ package org.jboss.test.ws.jaxws.cxf.jbws4430; import jakarta.jws.HandlerChain; +import org.apache.cxf.interceptor.OutInterceptors; @jakarta.jws.WebService(targetNamespace = "http://test.ws.jboss.org/", wsdlLocation = "WEB-INF/wsdl/HelloWorld.wsdl") @HandlerChain(file = "/handlers.xml") +@OutInterceptors(interceptors = {"org.jboss.test.ws.jaxws.cxf.jbws4430.CDIOutInterceptor"}) public class HelloBean { public HelloBean() { } diff --git a/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/JBWS4430TestCase.java b/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/JBWS4430TestCase.java index c14868ec5..43fc846ac 100644 --- a/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/JBWS4430TestCase.java +++ b/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/JBWS4430TestCase.java @@ -47,8 +47,8 @@ public class JBWS4430TestCase extends JBossWSTest { public static WebArchive createDeployment() { WebArchive archive = ShrinkWrap.create(WebArchive.class, DEP + ".war"); archive.setManifest(new StringAsset("Manifest-Version: 1.0\n" - + "Dependencies: org.apache.cxf\n")) - .addClasses(HelloBean.class, DelegateBean.class, EmptyBean.class, LoggingHandler.class) + + "Dependencies: org.jboss.ws.cxf.jbossws-cxf-server\n")) + .addClasses(HelloBean.class, DelegateBean.class, EmptyBean.class, CDIOutInterceptor.class, LoggingHandler.class) .addAsWebInfResource(new File(JBossWSTestHelper.getTestResourcesDir() + "/jaxws/cxf/jbws4430/WEB-INF/wsdl/HelloWorld.wsdl"), "wsdl/HelloWorld.wsdl") .add(new FileAsset(new File(JBossWSTestHelper.getTestResourcesDir() + "/jaxws/cxf/jbws4430/handlers.xml")), "WEB-INF/classes/handlers.xml") .setWebXML(new File(JBossWSTestHelper.getTestResourcesDir() + "/jaxws/cxf/jbws4430/WEB-INF/web.xml")); From 5996d347a0edec01d8247ed8e8773a7f00e2910f Mon Sep 17 00:00:00 2001 From: Jim Ma Date: Fri, 1 Nov 2024 14:11:52 +0800 Subject: [PATCH 3/3] [JBWS-4430]:Rename HandlerAuthInterceptor to HandlerConfigInterceptor;Improve comment and test --- .../stack/cxf/configuration/BusHolder.java | 6 ++--- ...tor.java => HandlerConfigInterceptor.java} | 27 ++++++++++--------- .../jaxws/cxf/jbws4430/CDIOutInterceptor.java | 1 + .../jaxws/cxf/jbws4430/JBWS4430TestCase.java | 2 +- 4 files changed, 19 insertions(+), 17 deletions(-) rename modules/server/src/main/java/org/jboss/wsf/stack/cxf/interceptor/{HandlerAuthInterceptor.java => HandlerConfigInterceptor.java} (91%) diff --git a/modules/server/src/main/java/org/jboss/wsf/stack/cxf/configuration/BusHolder.java b/modules/server/src/main/java/org/jboss/wsf/stack/cxf/configuration/BusHolder.java index ebd210db8..9b1188d98 100644 --- a/modules/server/src/main/java/org/jboss/wsf/stack/cxf/configuration/BusHolder.java +++ b/modules/server/src/main/java/org/jboss/wsf/stack/cxf/configuration/BusHolder.java @@ -87,7 +87,7 @@ import org.jboss.wsf.stack.cxf.i18n.Messages; import org.jboss.wsf.stack.cxf.interceptor.EndpointAssociationInterceptor; import org.jboss.wsf.stack.cxf.interceptor.GracefulShutdownInterceptor; -import org.jboss.wsf.stack.cxf.interceptor.HandlerAuthInterceptor; +import org.jboss.wsf.stack.cxf.interceptor.HandlerConfigInterceptor; import org.jboss.wsf.stack.cxf.interceptor.NsCtxSelectorStoreInterceptor; import org.jboss.wsf.stack.cxf.interceptor.WSDLSoapAddressRewriteInterceptor; import org.jboss.wsf.stack.cxf.management.InstrumentationManagerExtImpl; @@ -366,9 +366,9 @@ protected void setInterceptors(Bus bus, Deployment dep, Map prop final String p = (props != null) ? props.get(Constants.JBWS_CXF_DISABLE_HANDLER_AUTH_CHECKS) : null; if ((p == null || (!"true".equalsIgnoreCase(p) && !"1".equalsIgnoreCase(p))) && !Boolean.getBoolean(Constants.JBWS_CXF_DISABLE_HANDLER_AUTH_CHECKS)) { - bus.getInInterceptors().add(new HandlerAuthInterceptor()); + bus.getInInterceptors().add(new HandlerConfigInterceptor()); } else { - bus.getInInterceptors().add(new HandlerAuthInterceptor(true)); + bus.getInInterceptors().add(new HandlerConfigInterceptor(true)); } final SOAPAddressRewriteMetadata sarm = dep.getAttachment(SOAPAddressRewriteMetadata.class); diff --git a/modules/server/src/main/java/org/jboss/wsf/stack/cxf/interceptor/HandlerAuthInterceptor.java b/modules/server/src/main/java/org/jboss/wsf/stack/cxf/interceptor/HandlerConfigInterceptor.java similarity index 91% rename from modules/server/src/main/java/org/jboss/wsf/stack/cxf/interceptor/HandlerAuthInterceptor.java rename to modules/server/src/main/java/org/jboss/wsf/stack/cxf/interceptor/HandlerConfigInterceptor.java index 0ac55f806..4eea7dd10 100644 --- a/modules/server/src/main/java/org/jboss/wsf/stack/cxf/interceptor/HandlerAuthInterceptor.java +++ b/modules/server/src/main/java/org/jboss/wsf/stack/cxf/interceptor/HandlerConfigInterceptor.java @@ -47,38 +47,39 @@ import org.jboss.wsf.stack.cxf.JAXPDelegateClassLoader; /** - * Interceptor which checks the current principal is authorized to - * call a given handler - * + * Interceptor that configures a jbossws handler chain and can skip authentication. + * It set {@code JBossWSHandlerChainInvoker} to use correct Thread Context Class Loader + * and perform security checks before invoking the handlers. * @author alessio.soldano@jboss.com + * @author ema@redhat.com * @since 23-Sep-2013 */ -public class HandlerAuthInterceptor extends AbstractPhaseInterceptor +public class HandlerConfigInterceptor extends AbstractPhaseInterceptor { - private static final String KEY = HandlerAuthInterceptor.class.getName() + ".SECURITY_EXCEPTION"; + private static final String KEY = HandlerConfigInterceptor.class.getName() + ".SECURITY_EXCEPTION"; - private final boolean skip; - public HandlerAuthInterceptor() + private final boolean skipAuth; + public HandlerConfigInterceptor() { super(Phase.PRE_PROTOCOL_FRONTEND); addBefore(SOAPHandlerInterceptor.class.getName()); addBefore(LogicalHandlerInInterceptor.class.getName()); - skip = false; + skipAuth = false; } /** - * Create a {@code HandlerAuthInterceptor} that can optionally skip authentication. + * Create a {@code HandlerConfigInterceptor} that can optionally skip authentication. * When the authentication is skipped, it added a customized {@code JBossWSHandlerChainInvoker} * which set the correct TCCL to allow the handler to access CDI - * Please see + * Please see https://issues.redhat.com/browse/JBWS-4430 * This interceptor will be added to CXF interceptor chain * @param skipAuth a boolean flag indicating whether to skip authentication. **/ - public HandlerAuthInterceptor(boolean skipAuth) + public HandlerConfigInterceptor(boolean skipAuth) { super(Phase.PRE_PROTOCOL_FRONTEND); addBefore(SOAPHandlerInterceptor.class.getName()); addBefore(LogicalHandlerInInterceptor.class.getName()); - skip = skipAuth; + this.skipAuth = skipAuth; } @Override @@ -94,7 +95,7 @@ public void handleMessage(Message message) throws Fault @SuppressWarnings("rawtypes") final List handlerChain = ep.getJaxwsBinding().getHandlerChain(); if (handlerChain != null && !handlerChain.isEmpty()) { //save - invoker = new JBossWSHandlerChainInvoker(handlerChain, isOutbound(message, ex), skip); + invoker = new JBossWSHandlerChainInvoker(handlerChain, isOutbound(message, ex), skipAuth); ex.put(HandlerChainInvoker.class, invoker); } } diff --git a/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/CDIOutInterceptor.java b/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/CDIOutInterceptor.java index 41e356799..470af4b7a 100644 --- a/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/CDIOutInterceptor.java +++ b/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/CDIOutInterceptor.java @@ -20,6 +20,7 @@ import org.apache.cxf.interceptor.Fault; import org.apache.cxf.message.Message; import org.apache.cxf.message.MessageUtils; +import org.apache.cxf.phase.AbstractPhaseInterceptor; import org.apache.cxf.phase.Phase; import org.jboss.wsf.stack.cxf.interceptor.AbstractTCCLPhaseInterceptor; diff --git a/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/JBWS4430TestCase.java b/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/JBWS4430TestCase.java index 43fc846ac..6a85c7055 100644 --- a/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/JBWS4430TestCase.java +++ b/modules/testsuite/cxf-tests/src/test/java/org/jboss/test/ws/jaxws/cxf/jbws4430/JBWS4430TestCase.java @@ -47,7 +47,7 @@ public class JBWS4430TestCase extends JBossWSTest { public static WebArchive createDeployment() { WebArchive archive = ShrinkWrap.create(WebArchive.class, DEP + ".war"); archive.setManifest(new StringAsset("Manifest-Version: 1.0\n" - + "Dependencies: org.jboss.ws.cxf.jbossws-cxf-server\n")) + + "Dependencies: org.apache.cxf,org.jboss.ws.cxf.jbossws-cxf-server\n")) .addClasses(HelloBean.class, DelegateBean.class, EmptyBean.class, CDIOutInterceptor.class, LoggingHandler.class) .addAsWebInfResource(new File(JBossWSTestHelper.getTestResourcesDir() + "/jaxws/cxf/jbws4430/WEB-INF/wsdl/HelloWorld.wsdl"), "wsdl/HelloWorld.wsdl") .add(new FileAsset(new File(JBossWSTestHelper.getTestResourcesDir() + "/jaxws/cxf/jbws4430/handlers.xml")), "WEB-INF/classes/handlers.xml")