From d42a85cc28e72f5c5240903a6c760cbaeb05131e Mon Sep 17 00:00:00 2001 From: Jim Ma Date: Mon, 21 Oct 2024 20:13:29 +0800 Subject: [PATCH] [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 | 76 +++++++++++++++--- .../cxf/interceptor/SecurityActions.java | 79 +++++++++++++++++++ 4 files changed, 151 insertions(+), 9 deletions(-) create mode 100644 modules/server/src/main/java/org/jboss/wsf/stack/cxf/interceptor/SecurityActions.java 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..cdfc2a2fd 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,6 +44,7 @@ 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 @@ -55,13 +56,28 @@ public class HandlerAuthInterceptor extends AbstractPhaseInterceptor { private static final String KEY = HandlerAuthInterceptor.class.getName() + ".SECURITY_EXCEPTION"; - + private boolean skipAuth = false; public HandlerAuthInterceptor() { super(Phase.PRE_PROTOCOL_FRONTEND); addBefore(SOAPHandlerInterceptor.class.getName()); addBefore(LogicalHandlerInInterceptor.class.getName()); } + /** + * 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); + skipAuth = skipAuth; + addBefore(SOAPHandlerInterceptor.class.getName()); + addBefore(LogicalHandlerInInterceptor.class.getName()); + } @Override public void handleMessage(Message message) throws Fault @@ -76,7 +92,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)); + invoker = new JBossWSHandlerChainInvoker(handlerChain, isOutbound(message, ex), skipAuth); ex.put(HandlerChainInvoker.class, invoker); } } @@ -91,23 +107,47 @@ private boolean isOutbound(Message message, Exchange ex) { private static class JBossWSHandlerChainInvoker extends HandlerChainInvoker { - public JBossWSHandlerChainInvoker(@SuppressWarnings("rawtypes") List hc, boolean isOutbound) + private boolean skipAuth = false; + public JBossWSHandlerChainInvoker(@SuppressWarnings("rawtypes") List hc, boolean isOutbound, boolean skipAuth) { super(hc, isOutbound); + skipAuth = skipAuth; } @Override public boolean invokeLogicalHandlers(boolean requestor, LogicalMessageContext context) { - checkAuthorization(context); - return super.invokeLogicalHandlers(requestor, context); + if (!skipAuth) { + 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 (!skipAuth) { + 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 @@ -116,7 +156,16 @@ public boolean invokeLogicalHandlersHandleFault(boolean requestor, LogicalMessag if (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 @@ -125,7 +174,16 @@ public boolean invokeProtocolHandlersHandleFault(boolean requestor, MessageConte if (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) 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; + } + }); + } + } +}