diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/CommonScopeModelInitializer.java b/dubbo-common/src/main/java/org/apache/dubbo/common/CommonScopeModelInitializer.java index 29f242fe4a..b3748db1b8 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/CommonScopeModelInitializer.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/CommonScopeModelInitializer.java @@ -22,6 +22,7 @@ import org.apache.dubbo.common.convert.ConverterUtil; import org.apache.dubbo.common.lang.ShutdownHookCallbacks; import org.apache.dubbo.common.status.reporter.FrameworkStatusReportService; import org.apache.dubbo.common.threadpool.manager.FrameworkExecutorRepository; +import org.apache.dubbo.common.utils.SerializeSecurityManager; import org.apache.dubbo.rpc.model.ApplicationModel; import org.apache.dubbo.rpc.model.FrameworkModel; import org.apache.dubbo.rpc.model.ModuleModel; @@ -33,6 +34,7 @@ public class CommonScopeModelInitializer implements ScopeModelInitializer { ScopeBeanFactory beanFactory = frameworkModel.getBeanFactory(); beanFactory.registerBean(FrameworkExecutorRepository.class); beanFactory.registerBean(ConverterUtil.class); + beanFactory.registerBean(SerializeSecurityManager.class); } @Override diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java index a237c86fd5..a36742fe4c 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java @@ -435,6 +435,8 @@ public interface CommonConstants { String SERIALIZE_BLOCKED_LIST_FILE_PATH = "security/serialize.blockedlist"; + String SERIALIZE_ALLOW_LIST_FILE_PATH = "security/serialize.allowlist"; + String QOS_LIVE_PROBE_EXTENSION = "dubbo.application.liveness-probe"; String QOS_READY_PROBE_EXTENSION = "dubbo.application.readiness-probe"; diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/LoggerCodeConstants.java b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/LoggerCodeConstants.java index f033d3941a..506ddadd32 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/LoggerCodeConstants.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/LoggerCodeConstants.java @@ -291,6 +291,8 @@ public interface LoggerCodeConstants { String PROTOCOL_FAILED_DECODE = "4-20"; + String PROTOCOL_UNTRUSTED_SERIALIZE_CLASS = "4-21"; + // Config module String CONFIG_FAILED_CONNECT_REGISTRY = "5-1"; diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/AllowClassNotifyListener.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/AllowClassNotifyListener.java new file mode 100644 index 0000000000..2346e0dc2c --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/AllowClassNotifyListener.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.apache.dubbo.common.utils; + +import java.util.Set; + +public interface AllowClassNotifyListener { + + SerializeCheckStatus DEFAULT_STATUS = SerializeCheckStatus.WARN; + + void notify(SerializeCheckStatus status, Set prefixList); +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ClassLoaderResourceLoader.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ClassLoaderResourceLoader.java index fa180db2a2..1d542c5c33 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ClassLoaderResourceLoader.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ClassLoaderResourceLoader.java @@ -24,11 +24,11 @@ import java.io.IOException; import java.lang.ref.SoftReference; import java.lang.reflect.Field; import java.net.URL; +import java.util.Collection; import java.util.Collections; import java.util.Enumeration; import java.util.LinkedHashMap; import java.util.LinkedHashSet; -import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; @@ -46,7 +46,7 @@ public class ClassLoaderResourceLoader { GlobalResourcesRepository.registerGlobalDisposable(() -> destroy()); } - public static Map> loadResources(String fileName, List classLoaders) throws InterruptedException { + public static Map> loadResources(String fileName, Collection classLoaders) throws InterruptedException { Map> resources = new ConcurrentHashMap<>(); CountDownLatch countDownLatch = new CountDownLatch(classLoaders.size()); for (ClassLoader classLoader : classLoaders) { diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/SerializeCheckStatus.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/SerializeCheckStatus.java new file mode 100644 index 0000000000..0046168312 --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/SerializeCheckStatus.java @@ -0,0 +1,23 @@ +/* + * 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.apache.dubbo.common.utils; + +public enum SerializeCheckStatus { + DISABLED, + WARN, + STRICT, +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/SerializeClassChecker.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/SerializeClassChecker.java index 5b4eb04b38..ed0af8cabb 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/SerializeClassChecker.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/SerializeClassChecker.java @@ -17,7 +17,6 @@ package org.apache.dubbo.common.utils; import org.apache.dubbo.common.beanutil.JavaBeanSerializeUtil; -import org.apache.dubbo.common.config.ConfigurationUtils; import org.apache.dubbo.common.constants.CommonConstants; import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; import org.apache.dubbo.common.logger.LoggerFactory; @@ -52,10 +51,10 @@ public class SerializeClassChecker { private final AtomicLong counter = new AtomicLong(0); private SerializeClassChecker() { - String openCheckClass = ConfigurationUtils.getProperty(CommonConstants.CLASS_DESERIALIZE_OPEN_CHECK, "true"); + String openCheckClass = System.getProperty(CommonConstants.CLASS_DESERIALIZE_OPEN_CHECK, "true"); OPEN_CHECK_CLASS = Boolean.parseBoolean(openCheckClass); - String blockAllClassExceptAllow = ConfigurationUtils.getProperty(CLASS_DESERIALIZE_BLOCK_ALL, "false"); + String blockAllClassExceptAllow = System.getProperty(CLASS_DESERIALIZE_BLOCK_ALL, "false"); BLOCK_ALL_CLASS_EXCEPT_ALLOW = Boolean.parseBoolean(blockAllClassExceptAllow); @@ -79,8 +78,8 @@ public class SerializeClassChecker { logger.error(COMMON_IO_EXCEPTION, "", "", "Failed to load blocked class list! Will ignore default blocked list.", e); } - String allowedClassList = ConfigurationUtils.getProperty(CLASS_DESERIALIZE_ALLOWED_LIST, "").trim().toLowerCase(Locale.ROOT); - String blockedClassList = ConfigurationUtils.getProperty(CLASS_DESERIALIZE_BLOCKED_LIST, "").trim().toLowerCase(Locale.ROOT); + String allowedClassList = System.getProperty(CLASS_DESERIALIZE_ALLOWED_LIST, "").trim().toLowerCase(Locale.ROOT); + String blockedClassList = System.getProperty(CLASS_DESERIALIZE_BLOCKED_LIST, "").trim().toLowerCase(Locale.ROOT); if (StringUtils.isNotEmpty(allowedClassList)) { String[] classStrings = allowedClassList.trim().split(","); @@ -120,34 +119,45 @@ public class SerializeClassChecker { * @throws IllegalArgumentException if class is blocked */ public void validateClass(String name) { + validateClass(name, true); + } + + public boolean validateClass(String name, boolean failOnError) { if (!OPEN_CHECK_CLASS) { - return; + return true; } name = name.toLowerCase(Locale.ROOT); if (CACHE == CLASS_ALLOW_LFU_CACHE.get(name)) { - return; + return true; } if (CACHE == CLASS_BLOCK_LFU_CACHE.get(name)) { - error(name); + if (failOnError) { + error(name); + } + return false; } for (String allowedPrefix : CLASS_DESERIALIZE_ALLOWED_SET) { if (name.startsWith(allowedPrefix)) { CLASS_ALLOW_LFU_CACHE.put(name, CACHE); - return; + return true; } } for (String blockedPrefix : CLASS_DESERIALIZE_BLOCKED_SET) { if (BLOCK_ALL_CLASS_EXCEPT_ALLOW || name.startsWith(blockedPrefix)) { CLASS_BLOCK_LFU_CACHE.put(name, CACHE); - error(name); + if (failOnError) { + error(name); + } + return false; } } CLASS_ALLOW_LFU_CACHE.put(name, CACHE); + return true; } private void error(String name) { diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/SerializeSecurityManager.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/SerializeSecurityManager.java new file mode 100644 index 0000000000..6cea23a58d --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/SerializeSecurityManager.java @@ -0,0 +1,224 @@ +/* + * 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.apache.dubbo.common.utils; + +import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.GenericArrayType; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.lang.reflect.WildcardType; +import java.net.URL; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.rpc.model.FrameworkModel; + +import static org.apache.dubbo.common.constants.CommonConstants.SERIALIZE_ALLOW_LIST_FILE_PATH; +import static org.apache.dubbo.common.constants.LoggerCodeConstants.COMMON_IO_EXCEPTION; +import static org.apache.dubbo.common.constants.LoggerCodeConstants.INTERNAL_INTERRUPTED; + +public class SerializeSecurityManager { + private final Set allowedPrefix = new LinkedHashSet<>(); + + private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(SerializeSecurityManager.class); + + private final SerializeClassChecker checker = SerializeClassChecker.getInstance(); + + private final Set listeners = new ConcurrentHashSet<>(); + + private volatile SerializeCheckStatus checkStatus = AllowClassNotifyListener.DEFAULT_STATUS; + + public SerializeSecurityManager(FrameworkModel frameworkModel) { + try { + Set classLoaders = frameworkModel.getClassLoaders(); + List urls = ClassLoaderResourceLoader.loadResources(SERIALIZE_ALLOW_LIST_FILE_PATH, classLoaders) + .values() + .stream() + .flatMap(Set::stream) + .collect(Collectors.toList()); + for (URL u : urls) { + try { + logger.info("Read serialize allow list from " + u); + String[] lines = IOUtils.readLines(u.openStream()); + for (String line : lines) { + line = line.trim(); + if (StringUtils.isEmpty(line) || line.startsWith("#")) { + continue; + } + allowedPrefix.add(line); + } + } catch (IOException e) { + logger.error(COMMON_IO_EXCEPTION, "", "", "Failed to load allow class list! Will ignore allow lis from " + u, e); + } + } + } catch (InterruptedException e) { + logger.error(INTERNAL_INTERRUPTED, "", "", "Failed to load allow class list! Will ignore allow list from configuration.", e); + Thread.currentThread().interrupt(); + } + } + + public void registerInterface(Class clazz) { + Set> markedClass = new HashSet<>(); + markedClass.add(clazz); + + addToAllow(clazz.getName()); + + Method[] methodsToExport = clazz.getMethods(); + + for (Method method : methodsToExport) { + Class[] parameterTypes = method.getParameterTypes(); + for (Class parameterType : parameterTypes) { + checkClass(markedClass, parameterType); + } + + Type[] genericParameterTypes = method.getGenericParameterTypes(); + for (Type genericParameterType : genericParameterTypes) { + checkType(markedClass, genericParameterType); + } + + Class returnType = method.getReturnType(); + checkClass(markedClass, returnType); + + Type genericReturnType = method.getGenericReturnType(); + checkType(markedClass, genericReturnType); + + Class[] exceptionTypes = method.getExceptionTypes(); + for (Class exceptionType : exceptionTypes) { + checkClass(markedClass, exceptionType); + } + + Type[] genericExceptionTypes = method.getGenericExceptionTypes(); + for (Type genericExceptionType : genericExceptionTypes) { + checkType(markedClass, genericExceptionType); + } + } + } + + private void checkType(Set> markedClass, Type type) { + if (type instanceof Class) { + checkClass(markedClass, (Class) type); + } else if (type instanceof ParameterizedType) { + ParameterizedType parameterizedType = (ParameterizedType) type; + checkClass(markedClass, (Class) parameterizedType.getRawType()); + for (Type actualTypeArgument : parameterizedType.getActualTypeArguments()) { + checkType(markedClass, actualTypeArgument); + } + } else if (type instanceof GenericArrayType) { + GenericArrayType genericArrayType = (GenericArrayType) type; + checkType(markedClass, genericArrayType.getGenericComponentType()); + } else if (type instanceof TypeVariable) { + TypeVariable typeVariable = (TypeVariable) type; + for (Type bound : typeVariable.getBounds()) { + checkType(markedClass, bound); + } + } else if (type instanceof WildcardType) { + WildcardType wildcardType = (WildcardType) type; + for (Type bound : wildcardType.getUpperBounds()) { + checkType(markedClass, bound); + } + for (Type bound : wildcardType.getLowerBounds()) { + checkType(markedClass, bound); + } + } + } + + private void checkClass(Set> markedClass, Class clazz) { + if (markedClass.contains(clazz)) { + return; + } + + markedClass.add(clazz); + + addToAllow(clazz.getName()); + + Class[] interfaces = clazz.getInterfaces(); + for (Class interfaceClass : interfaces) { + checkClass(markedClass, interfaceClass); + } + + Class superclass = clazz.getSuperclass(); + if (superclass != null) { + checkClass(markedClass, superclass); + } + + Field[] fields = clazz.getDeclaredFields(); + + for (Field field : fields) { + if (Modifier.isTransient(field.getModifiers())) { + continue; + } + + Class fieldClass = field.getType(); + checkClass(markedClass, fieldClass); + checkType(markedClass, field.getGenericType()); + } + } + + protected void addToAllow(String className) { + if (!checker.validateClass(className, false)) { + return; + } + + boolean modified; + + // ignore jdk + if (className.startsWith("java.") || className.startsWith("javax.") || className.startsWith("com.sun.") || + className.startsWith("sun.") || className.startsWith("jdk.")) { + modified = allowedPrefix.add(className); + if (modified) { + notifyListeners(); + } + return; + } + + // add group package + String[] subs = className.split("\\."); + if (subs.length > 3) { + modified = allowedPrefix.add(subs[0] + "." + subs[1] + "." + subs[2]); + } else { + modified = allowedPrefix.add(className); + } + + if (modified) { + notifyListeners(); + } + } + + public void registerListener(AllowClassNotifyListener listener) { + listeners.add(listener); + listener.notify(checkStatus, allowedPrefix); + } + + private void notifyListeners() { + for (AllowClassNotifyListener listener : listeners) { + listener.notify(checkStatus, allowedPrefix); + } + } + + protected Set getAllowedPrefix() { + return allowedPrefix; + } +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/ApplicationConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/ApplicationConfig.java index 85b4173307..86eb5e440a 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/config/ApplicationConfig.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/config/ApplicationConfig.java @@ -16,6 +16,23 @@ */ package org.apache.dubbo.config; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.dubbo.common.compiler.support.AdaptiveCompiler; +import org.apache.dubbo.common.infra.InfraAdapter; +import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.utils.CollectionUtils; +import org.apache.dubbo.common.utils.StringUtils; +import org.apache.dubbo.config.support.Parameter; +import org.apache.dubbo.rpc.model.ApplicationModel; + import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY; import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_PROTOCOL_KEY; import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_VERSION_KEY; @@ -213,6 +230,11 @@ public class ApplicationConfig extends AbstractConfig { */ private Integer metadataServicePort; + /** + * The retry interval of service name mapping + */ + private Integer mappingRetryInterval; + /** * used to set extensions of probe in qos */ @@ -617,6 +639,14 @@ public class ApplicationConfig extends AbstractConfig { this.metadataServicePort = metadataServicePort; } + public Integer getMappingRetryInterval() { + return mappingRetryInterval; + } + + public void setMappingRetryInterval(Integer mappingRetryInterval) { + this.mappingRetryInterval = mappingRetryInterval; + } + @Parameter(key = METADATA_SERVICE_PROTOCOL_KEY) public String getMetadataServiceProtocol() { return metadataServiceProtocol; diff --git a/dubbo-common/src/main/resources/security/serialize.allowlist b/dubbo-common/src/main/resources/security/serialize.allowlist new file mode 100644 index 0000000000..bca85c1ca0 --- /dev/null +++ b/dubbo-common/src/main/resources/security/serialize.allowlist @@ -0,0 +1,125 @@ +# +# +# 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. +# +# +boolean +byte +char +double +float +int +long +short +java.lang.AutoCloseable +java.lang.Boolean +java.lang.Byte +java.lang.Character +java.lang.Class +java.lang.Cloneable +java.lang.Double +java.lang.Exception +java.lang.Float +java.lang.IllegalAccessError +java.lang.IllegalAccessException +java.lang.IllegalArgumentException +java.lang.IllegalMonitorStateException +java.lang.IllegalStateException +java.lang.IllegalThreadStateException +java.lang.IndexOutOfBoundsException +java.lang.InstantiationError +java.lang.InstantiationException +java.lang.Integer +java.lang.InternalError +java.lang.InterruptedException +java.lang.LinkageError +java.lang.Long +java.lang.NegativeArraySizeException +java.lang.NoClassDefFoundError +java.lang.NoSuchFieldError +java.lang.NoSuchFieldException +java.lang.NoSuchMethodError +java.lang.NoSuchMethodException +java.lang.NullPointerException +java.lang.Number +java.lang.NumberFormatException +java.lang.Object +java.lang.OutOfMemoryError +java.lang.RuntimeException +java.lang.SecurityException +java.lang.Short +java.lang.StackOverflowError +java.lang.StackTraceElement +java.lang.String +java.lang.StringIndexOutOfBoundsException +java.lang.TypeNotPresentException +java.lang.VerifyError +java.math.BigDecimal +java.math.BigInteger +java.text.SimpleDateFormat +java.time.format.DateTimeFormatter +java.time.Instant +java.time.LocalDate +java.time.LocalDateTime +java.time.LocalTime +java.util.ArrayList +java.util.Arrays$ArrayList +java.util.BitSet +java.util.Calendar +java.util.Collections$EmptyList +java.util.Collections$EmptyMap +java.util.Collections$SingletonSet +java.util.Collections$UnmodifiableCollection +java.util.Collections$UnmodifiableList +java.util.Collections$UnmodifiableMap +java.util.Collections$UnmodifiableNavigableMap +java.util.Collections$UnmodifiableNavigableSet +java.util.Collections$UnmodifiableRandomAccessList +java.util.Collections$UnmodifiableSet +java.util.Collections$UnmodifiableSortedMap +java.util.Collections$UnmodifiableSortedSet +java.util.concurrent.atomic.AtomicBoolean +java.util.concurrent.atomic.AtomicInteger +java.util.concurrent.atomic.AtomicIntegerArray +java.util.concurrent.atomic.AtomicLong +java.util.concurrent.atomic.AtomicLongArray +java.util.concurrent.atomic.AtomicReference +java.util.concurrent.ConcurrentHashMap +java.util.concurrent.ConcurrentLinkedQueue +java.util.concurrent.ConcurrentMap +java.util.concurrent.ConcurrentSkipListMap +java.util.concurrent.ConcurrentSkipListSet +java.util.concurrent.CopyOnWriteArrayList +java.util.concurrent.TimeUnit +java.util.Currency +java.util.Date +java.util.EnumSet +java.util.HashMap +java.util.HashSet +java.util.Hashtable +java.util.IdentityHashMap +java.util.LinkedHashMap +java.util.LinkedHashSet +java.util.LinkedList +java.util.List +java.util.Locale +java.util.Map +java.util.Set +java.util.TreeMap +java.util.TreeSet +java.util.UUID +java.util.WeakHashMap +org.apache.dubbo diff --git a/dubbo-common/src/main/resources/security/serialize.blockedlist b/dubbo-common/src/main/resources/security/serialize.blockedlist index de0b68de63..07bc753ccf 100644 --- a/dubbo-common/src/main/resources/security/serialize.blockedlist +++ b/dubbo-common/src/main/resources/security/serialize.blockedlist @@ -18,33 +18,38 @@ # aj.org.objectweb.asm. br.com.anteros. +bsh. ch.qos.logback. -clojure.core$constantly -clojure.main$eval_opt -com.alibaba.citrus.springext.support.parser.abstractnamedproxybeandefinitionparser$proxytargetfactory -com.alibaba.citrus.springext.util.springextutil.abstractproxy -com.alibaba.druid.pool.druiddatasource +clojure. +com.alibaba.citrus.springext.support.parser. +com.alibaba.citrus.springext.util.SpringExtUtil. +com.alibaba.druid.pool. com.alibaba.druid.stat.jdbcdatasourcestat com.alibaba.fastjson.annotation -com.alipay.custrelation.service.model.redress.pair +com.alibaba.hotcode.internal.org.apache.commons.collections.functors. +com.alipay.custrelation.service.model.redress. +com.alipay.oceanbase.obproxy.druid.pool. com.caucho. com.ibatis. +com.ibm.jtc.jax.xml.bind.v2.runtime.unmarshaller. +com.ibm.xltxe.rnm1.xtq.bcel.util. com.mchange com.mysql.cj.jdbc.admin. com.mysql.cj.jdbc.mysqlconnectionpooldatasource com.mysql.cj.jdbc.mysqldatasource com.mysql.cj.jdbc.mysqlxadatasource com.mysql.cj.log. +com.mysql.jdbc.util. com.p6spy.engine. -com.rometools.rome.feed.impl.equalsbean -com.rometools.rome.feed.impl.tostringbean +com.rometools.rome.feed. com.sun. com.taobao.eagleeye.wrapper +com.taobao.vipserver.commons.collections.functors. com.zaxxer.hikari. flex.messaging.util.concurrent. -java.awt.i -java.awt.p -java.beans.expression +groovy.lang. +java.awt. +java.beans. java.io.closeable java.io.serializable java.lang.autocloseable @@ -52,41 +57,46 @@ java.lang.class java.lang.cloneable java.lang.iterable java.lang.object +java.lang.ProcessBuilder java.lang.readable java.lang.runnable +java.lang.Runtime java.lang.thread java.lang.unixprocess java.net.inetaddress java.net.socket java.net.url java.rmi -java.security.signedobject +java.security. java.util.collection java.util.eventlistener java.util.jar. java.util.logging. java.util.prefs. +java.util.ServiceLoader java.util.serviceloader$lazyiterator +java.util.StringTokenizer javassist. javax.activation. -javax.imageio.imageio$containsfilter -javax.imageio.spi.serviceregistry +javax.imageio. javax.management. +javax.media.jai.remote. javax.naming. javax.net. javax.print. javax.script. javax.sound. -javax.swing.j +javax.swing. javax.tools. javax.xml jdk.internal. jodd.db.connection. junit. -net.bytebuddy.dynamic.loading.bytearrayclassloader +net.bytebuddy.dynamic.loading. net.sf.cglib. net.sf.ehcache.hibernate. net.sf.ehcache.transaction.manager. +ognl. oracle.jdbc. oracle.jms.aq oracle.net @@ -100,10 +110,12 @@ org.apache.aries.transaction. org.apache.axis2.jaxws.spi.handler. org.apache.axis2.transport.jms. org.apache.bcel +org.apache.carbondata.core.scan.expression. org.apache.carbondata.core.scan.expression.expressionresult org.apache.catalina. org.apache.cocoon. org.apache.commons.beanutils +org.apache.commons.codec. org.apache.commons.collections.comparators. org.apache.commons.collections.functors org.apache.commons.collections.functors. @@ -112,6 +124,7 @@ org.apache.commons.collections4.comparators org.apache.commons.collections4.functors org.apache.commons.collections4.transformer org.apache.commons.configuration +org.apache.commons.configuration2. org.apache.commons.dbcp org.apache.commons.fileupload org.apache.commons.jelly. @@ -130,32 +143,43 @@ org.apache.ibatis.ognl. org.apache.ibatis.parsing. org.apache.ibatis.reflection. org.apache.ibatis.scripting. +org.apache.ignite.cache. org.apache.ignite.cache.jta. +org.apache.log.output.db. org.apache.log4j. org.apache.logging. org.apache.myfaces.context.servlet +org.apache.myfaces.view.facelets.el. org.apache.openjpa.ee. -org.apache.shiro.jndi. -org.apache.shiro.realm. +org.apache.shiro. org.apache.tomcat +org.apache.velocity. org.apache.wicket.util org.apache.xalan org.apache.xbean. -org.apache.xpath.xpathcontext +org.apache.xpath. +org.apache.zookeeper. +org.aspectj. org.codehaus.groovy.runtime org.codehaus.jackson. +org.datanucleus.store.rdbms.datasource.dbcp.datasources. +org.dom4j. org.eclipse.jetty. -org.geotools.filter.constantexpression +org.geotools.filter. org.h2.jdbcx. org.h2.server. +org.h2.value. org.hibernate org.javasimon. org.jaxen. org.jboss org.jdom. org.jdom2.transform. +org.junit. org.logicalcobwebs. +org.mockito. org.mortbay.jetty. +org.mortbay.log. org.mozilla.javascript org.objectweb.asm. org.osjava.sj. @@ -163,5 +187,11 @@ org.python.core org.quartz. org.slf4j. org.springframework. -org.yaml.snakeyaml.tokens.directivetoken -sun.rmi.server.unicastref \ No newline at end of file +org.thymeleaf. +org.yaml.snakeyaml.tokens. +pstore.shaded.org.apache.commons.collections. +sun.print. +sun.rmi.server. +sun.rmi.transport. +weblogic.ejb20.internal. +weblogic.jms.common. diff --git a/dubbo-common/src/test/java/com/pojo/Demo1.java b/dubbo-common/src/test/java/com/pojo/Demo1.java new file mode 100644 index 0000000000..6713821437 --- /dev/null +++ b/dubbo-common/src/test/java/com/pojo/Demo1.java @@ -0,0 +1,29 @@ +/* + * 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 com.pojo; + +public class Demo1 { + private Simple simple; + + public Simple getSimple() { + return simple; + } + + public void setSimple(Simple simple) { + this.simple = simple; + } +} diff --git a/dubbo-common/src/test/java/com/pojo/Demo2.java b/dubbo-common/src/test/java/com/pojo/Demo2.java new file mode 100644 index 0000000000..9f7f5620b9 --- /dev/null +++ b/dubbo-common/src/test/java/com/pojo/Demo2.java @@ -0,0 +1,20 @@ +/* + * 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 com.pojo; + +public class Demo2 { +} diff --git a/dubbo-common/src/test/java/com/pojo/Demo3.java b/dubbo-common/src/test/java/com/pojo/Demo3.java new file mode 100644 index 0000000000..ea1f65baff --- /dev/null +++ b/dubbo-common/src/test/java/com/pojo/Demo3.java @@ -0,0 +1,20 @@ +/* + * 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 com.pojo; + +public class Demo3 { +} diff --git a/dubbo-common/src/test/java/com/pojo/Demo4.java b/dubbo-common/src/test/java/com/pojo/Demo4.java new file mode 100644 index 0000000000..3f12cca518 --- /dev/null +++ b/dubbo-common/src/test/java/com/pojo/Demo4.java @@ -0,0 +1,20 @@ +/* + * 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 com.pojo; + +public class Demo4 extends Demo3 { +} diff --git a/dubbo-common/src/test/java/com/pojo/Demo5.java b/dubbo-common/src/test/java/com/pojo/Demo5.java new file mode 100644 index 0000000000..e306ed1af5 --- /dev/null +++ b/dubbo-common/src/test/java/com/pojo/Demo5.java @@ -0,0 +1,20 @@ +/* + * 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 com.pojo; + +public class Demo5 { +} diff --git a/dubbo-common/src/test/java/com/pojo/Demo6.java b/dubbo-common/src/test/java/com/pojo/Demo6.java new file mode 100644 index 0000000000..890f6e2df8 --- /dev/null +++ b/dubbo-common/src/test/java/com/pojo/Demo6.java @@ -0,0 +1,20 @@ +/* + * 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 com.pojo; + +public class Demo6 { +} diff --git a/dubbo-common/src/test/java/com/pojo/Demo7.java b/dubbo-common/src/test/java/com/pojo/Demo7.java new file mode 100644 index 0000000000..06771c28a4 --- /dev/null +++ b/dubbo-common/src/test/java/com/pojo/Demo7.java @@ -0,0 +1,20 @@ +/* + * 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 com.pojo; + +public class Demo7 { +} diff --git a/dubbo-common/src/test/java/com/pojo/Demo8.java b/dubbo-common/src/test/java/com/pojo/Demo8.java new file mode 100644 index 0000000000..b991d5f3e2 --- /dev/null +++ b/dubbo-common/src/test/java/com/pojo/Demo8.java @@ -0,0 +1,20 @@ +/* + * 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 com.pojo; + +public class Demo8 { +} diff --git a/dubbo-common/src/test/java/com/pojo/DemoException1.java b/dubbo-common/src/test/java/com/pojo/DemoException1.java new file mode 100644 index 0000000000..0555fc7207 --- /dev/null +++ b/dubbo-common/src/test/java/com/pojo/DemoException1.java @@ -0,0 +1,20 @@ +/* + * 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 com.pojo; + +public class DemoException1 extends Exception{ +} diff --git a/dubbo-common/src/test/java/com/pojo/DemoException2.java b/dubbo-common/src/test/java/com/pojo/DemoException2.java new file mode 100644 index 0000000000..e880cfef7e --- /dev/null +++ b/dubbo-common/src/test/java/com/pojo/DemoException2.java @@ -0,0 +1,20 @@ +/* + * 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 com.pojo; + +public class DemoException2 extends Exception { +} diff --git a/dubbo-common/src/test/java/com/pojo/DemoException3.java b/dubbo-common/src/test/java/com/pojo/DemoException3.java new file mode 100644 index 0000000000..f842b0b4c7 --- /dev/null +++ b/dubbo-common/src/test/java/com/pojo/DemoException3.java @@ -0,0 +1,20 @@ +/* + * 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 com.pojo; + +public class DemoException3 extends DemoException2 { +} diff --git a/dubbo-common/src/test/java/com/pojo/Simple.java b/dubbo-common/src/test/java/com/pojo/Simple.java new file mode 100644 index 0000000000..62a1161292 --- /dev/null +++ b/dubbo-common/src/test/java/com/pojo/Simple.java @@ -0,0 +1,20 @@ +/* + * 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 com.pojo; + +public class Simple { +} diff --git a/dubbo-common/src/test/java/com/service/DemoService1.java b/dubbo-common/src/test/java/com/service/DemoService1.java new file mode 100644 index 0000000000..139fb69624 --- /dev/null +++ b/dubbo-common/src/test/java/com/service/DemoService1.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 com.service; + +import com.pojo.Demo1; +import com.pojo.Demo2; +import com.pojo.Demo4; +import com.pojo.Demo5; +import com.pojo.Demo6; +import com.pojo.Demo7; +import com.pojo.Demo8; +import com.pojo.DemoException1; +import com.pojo.DemoException3; + +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.Vector; + +public interface DemoService1 { + Demo1 getDemo1(); + + void setDemo2(Demo2 demo2); + + List getDemo4s(); + + List>>>>> getDemo5s(); + + List[] getDemo7s(); + + List getTs(); + + void echo1() throws DemoException1; + + void echo2() throws DemoException3; +} diff --git a/dubbo-common/src/test/java/com/service/DemoService2.java b/dubbo-common/src/test/java/com/service/DemoService2.java new file mode 100644 index 0000000000..ac2910bf7c --- /dev/null +++ b/dubbo-common/src/test/java/com/service/DemoService2.java @@ -0,0 +1,20 @@ +/* + * 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 com.service; + +public interface DemoService2 extends DemoService1 { +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/SerializeSecurityManagerTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/SerializeSecurityManagerTest.java new file mode 100644 index 0000000000..69eeaf2c25 --- /dev/null +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/SerializeSecurityManagerTest.java @@ -0,0 +1,128 @@ +/* + * 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.apache.dubbo.common.utils; + +import org.apache.dubbo.rpc.model.FrameworkModel; + +import com.service.DemoService1; +import com.service.DemoService2; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.Vector; + +public class SerializeSecurityManagerTest { + @Test + public void test() { + SerializeSecurityManager ssm = new SerializeSecurityManager(FrameworkModel.defaultModel()); + ssm.registerListener(new TestAllowClassNotifyListener()); + Assertions.assertTrue(ssm.getAllowedPrefix().contains("java.util.HashMap")); + Assertions.assertTrue(ssm.getAllowedPrefix().contains("com.example.DemoInterface")); + Assertions.assertTrue(ssm.getAllowedPrefix().contains("com.sun.Interface1")); + Assertions.assertFalse(ssm.getAllowedPrefix().contains("com.sun.Interface2")); + + Assertions.assertEquals(ssm.getAllowedPrefix(), TestAllowClassNotifyListener.getPrefixList()); + } + + @Test + public void addToAllow() { + SerializeSecurityManager ssm = new SerializeSecurityManager(FrameworkModel.defaultModel()); + ssm.registerListener(new TestAllowClassNotifyListener()); + Assertions.assertFalse(ssm.getAllowedPrefix().contains("com.sun.Interface2")); + Assertions.assertEquals(ssm.getAllowedPrefix(), TestAllowClassNotifyListener.getPrefixList()); + + ssm.addToAllow("com.sun.Interface2"); + Assertions.assertFalse(ssm.getAllowedPrefix().contains("com.sun.Interface2")); + Assertions.assertEquals(ssm.getAllowedPrefix(), TestAllowClassNotifyListener.getPrefixList()); + + ssm.addToAllow("java.util.Interface1"); + Assertions.assertTrue(ssm.getAllowedPrefix().contains("java.util.Interface1")); + Assertions.assertEquals(ssm.getAllowedPrefix(), TestAllowClassNotifyListener.getPrefixList()); + + ssm.addToAllow("java.util.package.Interface1"); + Assertions.assertTrue(ssm.getAllowedPrefix().contains("java.util.package.Interface1")); + Assertions.assertEquals(ssm.getAllowedPrefix(), TestAllowClassNotifyListener.getPrefixList()); + + ssm.addToAllow("com.example.Interface2"); + Assertions.assertTrue(ssm.getAllowedPrefix().contains("com.example.Interface2")); + Assertions.assertEquals(ssm.getAllowedPrefix(), TestAllowClassNotifyListener.getPrefixList()); + + ssm.addToAllow("com.example.package.Interface1"); + Assertions.assertTrue(ssm.getAllowedPrefix().contains("com.example.package")); + Assertions.assertEquals(ssm.getAllowedPrefix(), TestAllowClassNotifyListener.getPrefixList()); + } + + @Test + public void testRegister1() { + SerializeSecurityManager ssm = new SerializeSecurityManager(FrameworkModel.defaultModel()); + ssm.registerListener(new TestAllowClassNotifyListener()); + + ssm.registerInterface(DemoService1.class); + Assertions.assertTrue(ssm.getAllowedPrefix().contains("com.service.DemoService1")); + Assertions.assertTrue(ssm.getAllowedPrefix().contains("com.pojo.Demo1")); + Assertions.assertTrue(ssm.getAllowedPrefix().contains("com.pojo.Demo2")); + Assertions.assertTrue(ssm.getAllowedPrefix().contains("com.pojo.Demo3")); + Assertions.assertTrue(ssm.getAllowedPrefix().contains("com.pojo.Demo4")); + Assertions.assertTrue(ssm.getAllowedPrefix().contains("com.pojo.Demo5")); + Assertions.assertTrue(ssm.getAllowedPrefix().contains("com.pojo.Demo6")); + Assertions.assertTrue(ssm.getAllowedPrefix().contains("com.pojo.Demo7")); + Assertions.assertTrue(ssm.getAllowedPrefix().contains("com.pojo.Demo8")); + Assertions.assertTrue(ssm.getAllowedPrefix().contains("com.pojo.Simple")); + + Assertions.assertTrue(ssm.getAllowedPrefix().contains(List.class.getName())); + Assertions.assertTrue(ssm.getAllowedPrefix().contains(Set.class.getName())); + Assertions.assertTrue(ssm.getAllowedPrefix().contains(Map.class.getName())); + Assertions.assertTrue(ssm.getAllowedPrefix().contains(LinkedList.class.getName())); + Assertions.assertTrue(ssm.getAllowedPrefix().contains(Vector.class.getName())); + Assertions.assertTrue(ssm.getAllowedPrefix().contains(HashSet.class.getName())); + + Assertions.assertEquals(ssm.getAllowedPrefix(), TestAllowClassNotifyListener.getPrefixList()); + } + + + @Test + public void testRegister2() { + SerializeSecurityManager ssm = new SerializeSecurityManager(FrameworkModel.defaultModel()); + ssm.registerListener(new TestAllowClassNotifyListener()); + + ssm.registerInterface(DemoService2.class); + Assertions.assertTrue(ssm.getAllowedPrefix().contains("com.service.DemoService2")); + Assertions.assertTrue(ssm.getAllowedPrefix().contains("com.pojo.Demo1")); + Assertions.assertTrue(ssm.getAllowedPrefix().contains("com.pojo.Demo2")); + Assertions.assertTrue(ssm.getAllowedPrefix().contains("com.pojo.Demo3")); + Assertions.assertTrue(ssm.getAllowedPrefix().contains("com.pojo.Demo4")); + Assertions.assertTrue(ssm.getAllowedPrefix().contains("com.pojo.Demo5")); + Assertions.assertTrue(ssm.getAllowedPrefix().contains("com.pojo.Demo6")); + Assertions.assertTrue(ssm.getAllowedPrefix().contains("com.pojo.Demo7")); + Assertions.assertTrue(ssm.getAllowedPrefix().contains("com.pojo.Demo8")); + Assertions.assertTrue(ssm.getAllowedPrefix().contains("com.pojo.Simple")); + + Assertions.assertTrue(ssm.getAllowedPrefix().contains(List.class.getName())); + Assertions.assertTrue(ssm.getAllowedPrefix().contains(Set.class.getName())); + Assertions.assertTrue(ssm.getAllowedPrefix().contains(Map.class.getName())); + Assertions.assertTrue(ssm.getAllowedPrefix().contains(LinkedList.class.getName())); + Assertions.assertTrue(ssm.getAllowedPrefix().contains(Vector.class.getName())); + Assertions.assertTrue(ssm.getAllowedPrefix().contains(HashSet.class.getName())); + + Assertions.assertEquals(ssm.getAllowedPrefix(), TestAllowClassNotifyListener.getPrefixList()); + } +} diff --git a/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/dubbo/DefaultHessian2FactoryInitializer.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/TestAllowClassNotifyListener.java similarity index 53% rename from dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/dubbo/DefaultHessian2FactoryInitializer.java rename to dubbo-common/src/test/java/org/apache/dubbo/common/utils/TestAllowClassNotifyListener.java index cca8697030..362939cc4d 100644 --- a/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/dubbo/DefaultHessian2FactoryInitializer.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/TestAllowClassNotifyListener.java @@ -14,18 +14,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.dubbo.common.serialize.hessian2.dubbo; +package org.apache.dubbo.common.utils; -import org.apache.dubbo.common.serialize.hessian2.Hessian2SerializerFactory; +import java.util.Set; +import java.util.concurrent.atomic.AtomicReference; -import com.alibaba.com.caucho.hessian.io.SerializerFactory; +public class TestAllowClassNotifyListener implements AllowClassNotifyListener { + private final static AtomicReference> prefixList = new AtomicReference<>(); -public class DefaultHessian2FactoryInitializer extends AbstractHessian2FactoryInitializer { @Override - protected SerializerFactory createSerializerFactory() { - Hessian2SerializerFactory hessian2SerializerFactory = new Hessian2SerializerFactory(); - hessian2SerializerFactory.setAllowNonSerializable(Boolean.parseBoolean(System.getProperty("dubbo.hessian.allowNonSerializable", "false"))); - hessian2SerializerFactory.getClassFactory().allow("org.apache.dubbo.*"); - return hessian2SerializerFactory; + public void notify(SerializeCheckStatus status, Set prefixList) { + TestAllowClassNotifyListener.prefixList.set(prefixList); + } + + public static Set getPrefixList() { + return prefixList.get(); } } diff --git a/dubbo-common/src/test/resources/security/serialize.allowlist b/dubbo-common/src/test/resources/security/serialize.allowlist new file mode 100644 index 0000000000..0e7c6e7208 --- /dev/null +++ b/dubbo-common/src/test/resources/security/serialize.allowlist @@ -0,0 +1,20 @@ +# +# +# 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. +# +# +com.example.DemoInterface +com.sun.Interface1 diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java index 1d0785680f..5964873eb4 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java @@ -16,6 +16,18 @@ */ package org.apache.dubbo.config; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; + import org.apache.dubbo.common.URL; import org.apache.dubbo.common.URLBuilder; import org.apache.dubbo.common.Version; @@ -24,6 +36,7 @@ import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; import org.apache.dubbo.common.logger.LoggerFactory; import org.apache.dubbo.common.threadpool.manager.ExecutorRepository; +import org.apache.dubbo.common.threadpool.manager.FrameworkExecutorRepository; import org.apache.dubbo.common.url.component.ServiceConfigURL; import org.apache.dubbo.common.utils.ClassUtils; import org.apache.dubbo.common.utils.CollectionUtils; @@ -49,17 +62,6 @@ import org.apache.dubbo.rpc.model.ScopeModel; import org.apache.dubbo.rpc.model.ServiceDescriptor; import org.apache.dubbo.rpc.service.GenericService; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; - import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_KEY; import static org.apache.dubbo.common.constants.CommonConstants.ANY_VALUE; import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SEPARATOR; @@ -264,21 +266,41 @@ public class ServiceConfig extends ServiceConfigBase { exportedURLs.forEach(url -> { if (url.getParameters().containsKey(SERVICE_NAME_MAPPING_KEY)) { ServiceNameMapping serviceNameMapping = ServiceNameMapping.getDefaultExtension(getScopeModel()); - try { - boolean succeeded = serviceNameMapping.map(url); - if (succeeded) { - logger.info("Successfully registered interface application mapping for service " + url.getServiceKey()); - } else { - logger.error(CONFIG_SERVER_DISCONNECTED, "configuration server disconnected", "", "Failed register interface application mapping for service " + url.getServiceKey()); - } - } catch (Exception e) { - logger.error(CONFIG_SERVER_DISCONNECTED, "configuration server disconnected", "", "Failed register interface application mapping for service " + url.getServiceKey(), e); - } + ScheduledExecutorService scheduledExecutor = getScopeModel().getBeanFactory() + .getBean(FrameworkExecutorRepository.class).getSharedScheduledExecutor(); + mapServiceName(url, serviceNameMapping, scheduledExecutor); } }); onExported(); } + protected void mapServiceName(URL url, ServiceNameMapping serviceNameMapping, ScheduledExecutorService scheduledExecutor) { + if (!exported) { + return; + } + logger.info("Try to register interface application mapping for service " + url.getServiceKey()); + boolean succeeded = false; + try { + succeeded = serviceNameMapping.map(url); + if (succeeded) { + logger.info("Successfully registered interface application mapping for service " + url.getServiceKey()); + } else { + logger.error(CONFIG_SERVER_DISCONNECTED, "configuration server disconnected", "", "Failed register interface application mapping for service " + url.getServiceKey()); + } + } catch (Exception e) { + logger.error(CONFIG_SERVER_DISCONNECTED, "configuration server disconnected", "", "Failed register interface application mapping for service " + url.getServiceKey(), e); + } + if (!succeeded) { + scheduleToMapping(scheduledExecutor, serviceNameMapping, url); + } + } + + private void scheduleToMapping(ScheduledExecutorService scheduledExecutor, ServiceNameMapping serviceNameMapping, URL url) { + Integer mappingRetryInterval = getApplication().getMappingRetryInterval(); + scheduledExecutor.schedule(() -> mapServiceName(url, serviceNameMapping, scheduledExecutor), + mappingRetryInterval == null ? 5000 : mappingRetryInterval, TimeUnit.MILLISECONDS); + } + private void checkAndUpdateSubConfigs() { // Use default configs defined explicitly with global scope diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java index c019027c0e..043c974170 100644 --- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java +++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java @@ -1038,6 +1038,7 @@ class ReferenceConfigTest { @Test @DisabledForJreRange(min = JRE.JAVA_16) public void testDifferentClassLoaderRequest() throws Exception { + FrameworkModel frameworkModel = FrameworkModel.defaultModel(); String basePath = DemoService.class.getProtectionDomain().getCodeSource().getLocation().getFile(); basePath = java.net.URLDecoder.decode(basePath, "UTF-8"); ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); @@ -1046,7 +1047,7 @@ class ReferenceConfigTest { TestClassLoader2 classLoader3 = new TestClassLoader2(classLoader2, basePath); ApplicationConfig applicationConfig = new ApplicationConfig("TestApp"); - ApplicationModel applicationModel = new ApplicationModel(FrameworkModel.defaultModel()); + ApplicationModel applicationModel = new ApplicationModel(frameworkModel); applicationModel.getApplicationConfigManager().setApplication(applicationConfig); ModuleModel moduleModel = new ModuleModel(applicationModel); diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ServiceConfigTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ServiceConfigTest.java index 36acb7ed91..8adbc61a15 100644 --- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ServiceConfigTest.java +++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ServiceConfigTest.java @@ -17,6 +17,14 @@ package org.apache.dubbo.config; +import java.util.Collections; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.atomic.AtomicInteger; + import org.apache.dubbo.common.URL; import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.config.api.DemoService; @@ -27,22 +35,22 @@ import org.apache.dubbo.config.mock.MockRegistryFactory2; import org.apache.dubbo.config.mock.MockServiceListener; import org.apache.dubbo.config.mock.TestProxyFactory; import org.apache.dubbo.config.provider.impl.DemoServiceImpl; +import org.apache.dubbo.metadata.MappingListener; +import org.apache.dubbo.metadata.ServiceNameMapping; import org.apache.dubbo.registry.Registry; import org.apache.dubbo.rpc.Exporter; import org.apache.dubbo.rpc.Invoker; import org.apache.dubbo.rpc.Protocol; +import org.apache.dubbo.rpc.model.ApplicationModel; +import org.apache.dubbo.rpc.model.FrameworkModel; import org.apache.dubbo.rpc.service.GenericService; - -import com.google.common.collect.Lists; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mockito; -import java.util.Collections; -import java.util.Map; -import java.util.concurrent.CountDownLatch; +import com.google.common.collect.Lists; import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_KEY; import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY; @@ -59,6 +67,7 @@ import static org.apache.dubbo.remoting.Constants.BIND_IP_KEY; import static org.apache.dubbo.remoting.Constants.BIND_PORT_KEY; import static org.apache.dubbo.rpc.Constants.GENERIC_KEY; import static org.apache.dubbo.rpc.cluster.Constants.EXPORT_KEY; +import static org.awaitility.Awaitility.await; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; @@ -529,4 +538,80 @@ class ServiceConfigTest { service.export(); }); } + + @Test + void testMappingRetry() { + FrameworkModel frameworkModel = new FrameworkModel(); + ApplicationModel applicationModel = frameworkModel.newApplication(); + ServiceConfig serviceConfig = new ServiceConfig<>(applicationModel.newModule()); + serviceConfig.exported(); + ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1); + AtomicInteger count = new AtomicInteger(0); + ServiceNameMapping serviceNameMapping = new ServiceNameMapping() { + @Override + public boolean map(URL url) { + if (count.incrementAndGet() < 5) { + throw new RuntimeException(); + } + return count.get() > 10; + } + + @Override + public void initInterfaceAppMapping(URL subscribedURL) { + + } + + @Override + public Set getAndListen(URL registryURL, URL subscribedURL, MappingListener listener) { + return null; + } + + @Override + public MappingListener stopListen(URL subscribeURL, MappingListener listener) { + return null; + } + + @Override + public void putCachedMapping(String serviceKey, Set apps) { + + } + + @Override + public Set getCachedMapping(String mappingKey) { + return null; + } + + @Override + public Set getCachedMapping(URL consumerURL) { + return null; + } + + @Override + public Set getRemoteMapping(URL consumerURL) { + return null; + } + + @Override + public Map> getCachedMapping() { + return null; + } + + @Override + public Set removeCachedMapping(String serviceKey) { + return null; + } + + @Override + public void $destroy() { + + } + }; + ApplicationConfig applicationConfig = new ApplicationConfig("app"); + applicationConfig.setMappingRetryInterval(10); + serviceConfig.setApplication(applicationConfig); + serviceConfig.mapServiceName(URL.valueOf(""), serviceNameMapping, scheduledExecutorService); + + await().until(() -> count.get() > 10); + scheduledExecutorService.shutdown(); + } } diff --git a/dubbo-config/dubbo-config-api/src/test/resources/security/serialize.allowlist b/dubbo-config/dubbo-config-api/src/test/resources/security/serialize.allowlist new file mode 100644 index 0000000000..ddd7fa8e4c --- /dev/null +++ b/dubbo-config/dubbo-config-api/src/test/resources/security/serialize.allowlist @@ -0,0 +1,19 @@ +# +# +# 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. +# +# +demo. diff --git a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd index 5df2073329..11a1b9f5bb 100644 --- a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd +++ b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd @@ -482,6 +482,11 @@ + + + + + diff --git a/dubbo-demo/dubbo-demo-triple/pom.xml b/dubbo-demo/dubbo-demo-triple/pom.xml index 6597e0c011..63979e1494 100644 --- a/dubbo-demo/dubbo-demo-triple/pom.xml +++ b/dubbo-demo/dubbo-demo-triple/pom.xml @@ -34,6 +34,7 @@ true 1.8 1.8 + 3.18.3 3.7.0 @@ -118,6 +119,7 @@ com.google.protobuf protobuf-java + ${protobuf-java.version} @@ -141,7 +143,7 @@ protobuf-maven-plugin 0.6.1 - com.google.protobuf:protoc:3.7.1:exe:${os.detected.classifier} + com.google.protobuf:protoc:${protobuf-java.version}:exe:${os.detected.classifier} triple-java build/generated/source/proto/main/java diff --git a/dubbo-dependencies-bom/pom.xml b/dubbo-dependencies-bom/pom.xml index 0bb37e2663..3d8a0ab491 100644 --- a/dubbo-dependencies-bom/pom.xml +++ b/dubbo-dependencies-bom/pom.xml @@ -113,7 +113,7 @@ 3.1.15 0.15.0 4.0.38 - 3.16.3 + 3.18.3 1.3.2 3.1.0 9.4.43.v20210629 @@ -914,4 +914,5 @@ + diff --git a/dubbo-distribution/dubbo-all/pom.xml b/dubbo-distribution/dubbo-all/pom.xml index f14687efb2..277f85b2ef 100644 --- a/dubbo-distribution/dubbo-all/pom.xml +++ b/dubbo-distribution/dubbo-all/pom.xml @@ -644,12 +644,6 @@ META-INF/dubbo/internal/org.apache.dubbo.common.serialize.Serialization - - - META-INF/dubbo/internal/org.apache.dubbo.common.serialize.hessian2.dubbo.Hessian2FactoryInitializer - - diff --git a/dubbo-distribution/dubbo-core-spi/pom.xml b/dubbo-distribution/dubbo-core-spi/pom.xml index 6ad50cb2f4..51e86c4c19 100644 --- a/dubbo-distribution/dubbo-core-spi/pom.xml +++ b/dubbo-distribution/dubbo-core-spi/pom.xml @@ -274,12 +274,6 @@ META-INF/dubbo/internal/org.apache.dubbo.common.serialize.Serialization - - - META-INF/dubbo/internal/org.apache.dubbo.common.serialize.hessian2.dubbo.Hessian2FactoryInitializer - - diff --git a/dubbo-native-plugin/src/main/resources/META-INF/native-image/reflect-config.json b/dubbo-native-plugin/src/main/resources/META-INF/native-image/reflect-config.json index 46630aff4d..fb1028af76 100644 --- a/dubbo-native-plugin/src/main/resources/META-INF/native-image/reflect-config.json +++ b/dubbo-native-plugin/src/main/resources/META-INF/native-image/reflect-config.json @@ -1065,19 +1065,6 @@ } ] }, - { - "name": "org.apache.dubbo.common.serialize.hessian2.dubbo.DefaultHessian2FactoryInitializer", - "allPublicMethods": true, - "methods": [ - { - "name": "", - "parameterTypes": [] - } - ] - }, - { - "name": "org.apache.dubbo.common.serialize.hessian2.dubbo.WhitelistHessian2FactoryInitializer" - }, { "name": "org.apache.dubbo.common.status.reporter.FrameworkStatusReportService", "methods": [ diff --git a/dubbo-native-plugin/src/main/resources/META-INF/native-image/resource-config.json b/dubbo-native-plugin/src/main/resources/META-INF/native-image/resource-config.json index 977e6eb3d1..f8deec494a 100644 --- a/dubbo-native-plugin/src/main/resources/META-INF/native-image/resource-config.json +++ b/dubbo-native-plugin/src/main/resources/META-INF/native-image/resource-config.json @@ -28,9 +28,6 @@ { "pattern": "\\QMETA-INF/dubbo/internal/org.apache.dubbo.common.serialize.Serialization\\E" }, - { - "pattern": "\\QMETA-INF/dubbo/internal/org.apache.dubbo.common.serialize.hessian2.dubbo.Hessian2FactoryInitializer\\E" - }, { "pattern": "\\QMETA-INF/dubbo/internal/org.apache.dubbo.common.threadpool.ThreadPool\\E" }, diff --git a/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/function/NacosConsumer.java b/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/function/NacosConsumer.java new file mode 100644 index 0000000000..1fd3557426 --- /dev/null +++ b/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/function/NacosConsumer.java @@ -0,0 +1,40 @@ +/* + * 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.apache.dubbo.registry.nacos.function; + +import java.util.function.Function; + +import com.alibaba.nacos.api.exception.NacosException; + +/** + * A function interface for action with {@link NacosException} + * + * @see Function + * @see NacosException + * @since 3.1.5 + */ +@FunctionalInterface +public interface NacosConsumer { + + /** + * Applies this function to the given argument. + * + * @param t the function argument + * @throws NacosException if met with any error + */ + void accept(T t) throws NacosException; +} diff --git a/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/function/NacosFunction.java b/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/function/NacosFunction.java new file mode 100644 index 0000000000..1d0050b75f --- /dev/null +++ b/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/function/NacosFunction.java @@ -0,0 +1,41 @@ +/* + * 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.apache.dubbo.registry.nacos.function; + +import java.util.function.Function; + +import com.alibaba.nacos.api.exception.NacosException; + +/** + * A function interface for action with {@link NacosException} + * + * @see Function + * @see NacosException + * @since 3.1.5 + */ +@FunctionalInterface +public interface NacosFunction { + + /** + * Applies this function to the given argument. + * + * @param t the function argument + * @return the function result + * @throws NacosException if met with any error + */ + R apply(T t) throws NacosException; +} diff --git a/dubbo-registry/dubbo-registry-nacos/src/test/java/org/apache/dubbo/registry/nacos/MockNamingService.java b/dubbo-registry/dubbo-registry-nacos/src/test/java/org/apache/dubbo/registry/nacos/MockNamingService.java new file mode 100644 index 0000000000..e6e7896908 --- /dev/null +++ b/dubbo-registry/dubbo-registry-nacos/src/test/java/org/apache/dubbo/registry/nacos/MockNamingService.java @@ -0,0 +1,289 @@ +/* + * 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.apache.dubbo.registry.nacos; + +import java.util.List; + +import com.alibaba.nacos.api.exception.NacosException; +import com.alibaba.nacos.api.naming.NamingService; +import com.alibaba.nacos.api.naming.listener.EventListener; +import com.alibaba.nacos.api.naming.pojo.Instance; +import com.alibaba.nacos.api.naming.pojo.ListView; +import com.alibaba.nacos.api.naming.pojo.ServiceInfo; +import com.alibaba.nacos.api.selector.AbstractSelector; + +public class MockNamingService implements NamingService { + @Override + public void registerInstance(String serviceName, String ip, int port) throws NacosException { + + } + + @Override + public void registerInstance(String serviceName, String groupName, String ip, int port) throws NacosException { + + } + + @Override + public void registerInstance(String serviceName, String ip, int port, String clusterName) throws NacosException { + + } + + @Override + public void registerInstance(String serviceName, String groupName, String ip, int port, String clusterName) throws NacosException { + + } + + @Override + public void registerInstance(String serviceName, Instance instance) throws NacosException { + + } + + @Override + public void registerInstance(String serviceName, String groupName, Instance instance) throws NacosException { + + } + + @Override + public void batchRegisterInstance(String serviceName, String groupName, List instances) throws NacosException { + + } + + @Override + public void deregisterInstance(String serviceName, String ip, int port) throws NacosException { + + } + + @Override + public void deregisterInstance(String serviceName, String groupName, String ip, int port) throws NacosException { + + } + + @Override + public void deregisterInstance(String serviceName, String ip, int port, String clusterName) throws NacosException { + + } + + @Override + public void deregisterInstance(String serviceName, String groupName, String ip, int port, String clusterName) throws NacosException { + + } + + @Override + public void deregisterInstance(String serviceName, Instance instance) throws NacosException { + + } + + @Override + public void deregisterInstance(String serviceName, String groupName, Instance instance) throws NacosException { + + } + + @Override + public List getAllInstances(String serviceName) throws NacosException { + return null; + } + + @Override + public List getAllInstances(String serviceName, String groupName) throws NacosException { + return null; + } + + @Override + public List getAllInstances(String serviceName, boolean subscribe) throws NacosException { + return null; + } + + @Override + public List getAllInstances(String serviceName, String groupName, boolean subscribe) throws NacosException { + return null; + } + + @Override + public List getAllInstances(String serviceName, List clusters) throws NacosException { + return null; + } + + @Override + public List getAllInstances(String serviceName, String groupName, List clusters) throws NacosException { + return null; + } + + @Override + public List getAllInstances(String serviceName, List clusters, boolean subscribe) throws NacosException { + return null; + } + + @Override + public List getAllInstances(String serviceName, String groupName, List clusters, boolean subscribe) throws NacosException { + return null; + } + + @Override + public List selectInstances(String serviceName, boolean healthy) throws NacosException { + return null; + } + + @Override + public List selectInstances(String serviceName, String groupName, boolean healthy) throws NacosException { + return null; + } + + @Override + public List selectInstances(String serviceName, boolean healthy, boolean subscribe) throws NacosException { + return null; + } + + @Override + public List selectInstances(String serviceName, String groupName, boolean healthy, boolean subscribe) throws NacosException { + return null; + } + + @Override + public List selectInstances(String serviceName, List clusters, boolean healthy) throws NacosException { + return null; + } + + @Override + public List selectInstances(String serviceName, String groupName, List clusters, boolean healthy) throws NacosException { + return null; + } + + @Override + public List selectInstances(String serviceName, List clusters, boolean healthy, boolean subscribe) throws NacosException { + return null; + } + + @Override + public List selectInstances(String serviceName, String groupName, List clusters, boolean healthy, boolean subscribe) throws NacosException { + return null; + } + + @Override + public Instance selectOneHealthyInstance(String serviceName) throws NacosException { + return null; + } + + @Override + public Instance selectOneHealthyInstance(String serviceName, String groupName) throws NacosException { + return null; + } + + @Override + public Instance selectOneHealthyInstance(String serviceName, boolean subscribe) throws NacosException { + return null; + } + + @Override + public Instance selectOneHealthyInstance(String serviceName, String groupName, boolean subscribe) throws NacosException { + return null; + } + + @Override + public Instance selectOneHealthyInstance(String serviceName, List clusters) throws NacosException { + return null; + } + + @Override + public Instance selectOneHealthyInstance(String serviceName, String groupName, List clusters) throws NacosException { + return null; + } + + @Override + public Instance selectOneHealthyInstance(String serviceName, List clusters, boolean subscribe) throws NacosException { + return null; + } + + @Override + public Instance selectOneHealthyInstance(String serviceName, String groupName, List clusters, boolean subscribe) throws NacosException { + return null; + } + + @Override + public void subscribe(String serviceName, EventListener listener) throws NacosException { + + } + + @Override + public void subscribe(String serviceName, String groupName, EventListener listener) throws NacosException { + + } + + @Override + public void subscribe(String serviceName, List clusters, EventListener listener) throws NacosException { + + } + + @Override + public void subscribe(String serviceName, String groupName, List clusters, EventListener listener) throws NacosException { + + } + + @Override + public void unsubscribe(String serviceName, EventListener listener) throws NacosException { + + } + + @Override + public void unsubscribe(String serviceName, String groupName, EventListener listener) throws NacosException { + + } + + @Override + public void unsubscribe(String serviceName, List clusters, EventListener listener) throws NacosException { + + } + + @Override + public void unsubscribe(String serviceName, String groupName, List clusters, EventListener listener) throws NacosException { + + } + + @Override + public ListView getServicesOfServer(int pageNo, int pageSize) throws NacosException { + return null; + } + + @Override + public ListView getServicesOfServer(int pageNo, int pageSize, String groupName) throws NacosException { + return null; + } + + @Override + public ListView getServicesOfServer(int pageNo, int pageSize, AbstractSelector selector) throws NacosException { + return null; + } + + @Override + public ListView getServicesOfServer(int pageNo, int pageSize, String groupName, AbstractSelector selector) throws NacosException { + return null; + } + + @Override + public List getSubscribeServices() throws NacosException { + return null; + } + + @Override + public String getServerStatus() { + return null; + } + + @Override + public void shutDown() throws NacosException { + + } +} diff --git a/dubbo-registry/dubbo-registry-nacos/src/test/java/org/apache/dubbo/registry/nacos/NacosRegistryTest.java b/dubbo-registry/dubbo-registry-nacos/src/test/java/org/apache/dubbo/registry/nacos/NacosRegistryTest.java index 1acb68981a..c2dbc42059 100644 --- a/dubbo-registry/dubbo-registry-nacos/src/test/java/org/apache/dubbo/registry/nacos/NacosRegistryTest.java +++ b/dubbo-registry/dubbo-registry-nacos/src/test/java/org/apache/dubbo/registry/nacos/NacosRegistryTest.java @@ -16,9 +16,19 @@ */ package org.apache.dubbo.registry.nacos; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + import org.apache.dubbo.common.URL; import org.apache.dubbo.common.utils.NetUtils; import org.apache.dubbo.registry.NotifyListener; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import com.alibaba.nacos.api.common.Constants; import com.alibaba.nacos.api.exception.NacosException; @@ -26,16 +36,6 @@ import com.alibaba.nacos.api.naming.NamingService; import com.alibaba.nacos.api.naming.pojo.Instance; import com.alibaba.nacos.api.naming.pojo.ListView; import com.alibaba.nacos.client.naming.NacosNamingService; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY; import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY; @@ -103,7 +103,7 @@ class NacosRegistryTest { // ignore } - NacosNamingServiceWrapper nacosNamingServiceWrapper = new NacosNamingServiceWrapper(new NacosConnectionManager(namingService)); + NacosNamingServiceWrapper nacosNamingServiceWrapper = new NacosNamingServiceWrapper(new NacosConnectionManager(namingService, 0, 0)); nacosRegistry = new NacosRegistry(this.registryUrl, nacosNamingServiceWrapper); Set registered; @@ -143,7 +143,7 @@ class NacosRegistryTest { // ignore } - NacosNamingServiceWrapper nacosNamingServiceWrapper = new NacosNamingServiceWrapper(new NacosConnectionManager(namingService)); + NacosNamingServiceWrapper nacosNamingServiceWrapper = new NacosNamingServiceWrapper(new NacosConnectionManager(namingService, 0, 0)); nacosRegistry = new NacosRegistry(this.registryUrl, nacosNamingServiceWrapper); nacosRegistry.register(serviceUrl); @@ -183,7 +183,7 @@ class NacosRegistryTest { // ignore } - NacosNamingServiceWrapper nacosNamingServiceWrapper = new NacosNamingServiceWrapper(new NacosConnectionManager(namingService)); + NacosNamingServiceWrapper nacosNamingServiceWrapper = new NacosNamingServiceWrapper(new NacosConnectionManager(namingService, 0, 0)); nacosRegistry = new NacosRegistry(this.registryUrl, nacosNamingServiceWrapper); NotifyListener listener = mock(NotifyListener.class); @@ -222,7 +222,7 @@ class NacosRegistryTest { } NacosNamingServiceWrapper nacosNamingServiceWrapper = new - NacosNamingServiceWrapper(new NacosConnectionManager(namingService)); + NacosNamingServiceWrapper(new NacosConnectionManager(namingService, 0, 0)); nacosRegistry = new NacosRegistry(this.registryUrl, nacosNamingServiceWrapper); NotifyListener listener = mock(NotifyListener.class); @@ -276,7 +276,7 @@ class NacosRegistryTest { } NacosNamingServiceWrapper nacosNamingServiceWrapper = new - NacosNamingServiceWrapper(new NacosConnectionManager(namingService)); + NacosNamingServiceWrapper(new NacosConnectionManager(namingService, 0, 0)); nacosRegistry = new NacosRegistry(this.registryUrl, nacosNamingServiceWrapper); Set registered; diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/ProtocolSecurityWrapper.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/ProtocolSecurityWrapper.java new file mode 100644 index 0000000000..d343009377 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/ProtocolSecurityWrapper.java @@ -0,0 +1,91 @@ +/* + * 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.apache.dubbo.rpc.protocol; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.Activate; +import org.apache.dubbo.common.utils.SerializeSecurityManager; +import org.apache.dubbo.rpc.Exporter; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.Protocol; +import org.apache.dubbo.rpc.ProtocolServer; +import org.apache.dubbo.rpc.RpcException; +import org.apache.dubbo.rpc.model.ScopeModel; +import org.apache.dubbo.rpc.model.ScopeModelUtil; +import org.apache.dubbo.rpc.model.ServiceDescriptor; +import org.apache.dubbo.rpc.model.ServiceModel; + +import java.util.List; +import java.util.Optional; + +@Activate(order = 200) +public class ProtocolSecurityWrapper implements Protocol { + private final Protocol protocol; + + public ProtocolSecurityWrapper(Protocol protocol) { + if (protocol == null) { + throw new IllegalArgumentException("protocol == null"); + } + this.protocol = protocol; + } + + @Override + public int getDefaultPort() { + return protocol.getDefaultPort(); + } + + @Override + public Exporter export(Invoker invoker) throws RpcException { + ServiceModel serviceModel = invoker.getUrl().getServiceModel(); + ScopeModel scopeModel = invoker.getUrl().getScopeModel(); + Optional.ofNullable(serviceModel) + .map(ServiceModel::getServiceModel) + .map(ServiceDescriptor::getServiceInterfaceClass) + .ifPresent((interfaceClass) -> { + SerializeSecurityManager serializeSecurityManager = ScopeModelUtil.getFrameworkModel(scopeModel) + .getBeanFactory().getBean(SerializeSecurityManager.class); + serializeSecurityManager.registerInterface(interfaceClass); + }); + return protocol.export(invoker); + } + + @Override + public Invoker refer(Class type, URL url) throws RpcException { + ServiceModel serviceModel = url.getServiceModel(); + ScopeModel scopeModel = url.getScopeModel(); + SerializeSecurityManager serializeSecurityManager = ScopeModelUtil.getFrameworkModel(scopeModel) + .getBeanFactory().getBean(SerializeSecurityManager.class); + + Optional.ofNullable(serviceModel) + .map(ServiceModel::getServiceModel) + .map(ServiceDescriptor::getServiceInterfaceClass) + .ifPresent(serializeSecurityManager::registerInterface); + serializeSecurityManager.registerInterface(type); + + return protocol.refer(type, url); + } + + @Override + public void destroy() { + protocol.destroy(); + } + + @Override + public List getServers() { + return protocol.getServers(); + } +} diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.Protocol b/dubbo-rpc/dubbo-rpc-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.Protocol index ab69b9c74f..eff2b090d6 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.Protocol +++ b/dubbo-rpc/dubbo-rpc-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.Protocol @@ -1,3 +1,4 @@ listener=org.apache.dubbo.rpc.protocol.ProtocolListenerWrapper mock=org.apache.dubbo.rpc.support.MockProtocol serializationwrapper=org.apache.dubbo.rpc.protocol.ProtocolSerializationWrapper +securitywrapper=org.apache.dubbo.rpc.protocol.ProtocolSecurityWrapper diff --git a/dubbo-rpc/dubbo-rpc-triple/pom.xml b/dubbo-rpc/dubbo-rpc-triple/pom.xml index eeca0e6937..d024a20a5e 100644 --- a/dubbo-rpc/dubbo-rpc-triple/pom.xml +++ b/dubbo-rpc/dubbo-rpc-triple/pom.xml @@ -32,6 +32,7 @@ 0.0.4.1-SNAPSHOT 1.0.4 3.4.19 + 3.18.3 @@ -52,6 +53,7 @@ com.google.protobuf protobuf-java + ${protobuf-java.version} org.springframework @@ -112,7 +114,7 @@ 0.6.1 - com.google.protobuf:protoc:3.11.0:exe:${os.detected.classifier} + com.google.protobuf:protoc:${protobuf-java.version}:exe:${os.detected.classifier} diff --git a/dubbo-serialization/dubbo-serialization-fastjson2/src/main/java/org/apache/dubbo/common/serialize/fastjson2/FastJson2ObjectInput.java b/dubbo-serialization/dubbo-serialization-fastjson2/src/main/java/org/apache/dubbo/common/serialize/fastjson2/FastJson2ObjectInput.java index 10b14dd6cc..d5975fdba6 100644 --- a/dubbo-serialization/dubbo-serialization-fastjson2/src/main/java/org/apache/dubbo/common/serialize/fastjson2/FastJson2ObjectInput.java +++ b/dubbo-serialization/dubbo-serialization-fastjson2/src/main/java/org/apache/dubbo/common/serialize/fastjson2/FastJson2ObjectInput.java @@ -32,11 +32,15 @@ public class FastJson2ObjectInput implements ObjectInput { private final Fastjson2CreatorManager fastjson2CreatorManager; + private final Fastjson2SecurityManager fastjson2SecurityManager; + private volatile ClassLoader classLoader; private final InputStream is; - public FastJson2ObjectInput(Fastjson2CreatorManager fastjson2CreatorManager, InputStream in) { + public FastJson2ObjectInput(Fastjson2CreatorManager fastjson2CreatorManager, + Fastjson2SecurityManager fastjson2SecurityManager, InputStream in) { this.fastjson2CreatorManager = fastjson2CreatorManager; + this.fastjson2SecurityManager = fastjson2SecurityManager; this.classLoader = Thread.currentThread().getContextClassLoader(); this.is = in; fastjson2CreatorManager.setCreator(classLoader); @@ -107,8 +111,9 @@ public class FastJson2ObjectInput implements ObjectInput { if (read != length) { throw new IllegalArgumentException("deserialize failed. expected read length: " + length + " but actual read: " + read); } - return (T) JSONB.parseObject(bytes, Object.class, JSONReader.Feature.SupportAutoType, + return (T) JSONB.parseObject(bytes, Object.class, fastjson2SecurityManager.getSecurityFilter(), JSONReader.Feature.UseDefaultConstructorAsPossible, + JSONReader.Feature.ErrorOnNoneSerializable, JSONReader.Feature.UseNativeObject, JSONReader.Feature.FieldBased); } @@ -123,8 +128,9 @@ public class FastJson2ObjectInput implements ObjectInput { if (read != length) { throw new IllegalArgumentException("deserialize failed. expected read length: " + length + " but actual read: " + read); } - return (T) JSONB.parseObject(bytes, Object.class, JSONReader.Feature.SupportAutoType, + return (T) JSONB.parseObject(bytes, Object.class, fastjson2SecurityManager.getSecurityFilter(), JSONReader.Feature.UseDefaultConstructorAsPossible, + JSONReader.Feature.ErrorOnNoneSerializable, JSONReader.Feature.UseNativeObject, JSONReader.Feature.FieldBased); } diff --git a/dubbo-serialization/dubbo-serialization-fastjson2/src/main/java/org/apache/dubbo/common/serialize/fastjson2/FastJson2ObjectOutput.java b/dubbo-serialization/dubbo-serialization-fastjson2/src/main/java/org/apache/dubbo/common/serialize/fastjson2/FastJson2ObjectOutput.java index fdf15aeba3..97c099f27b 100644 --- a/dubbo-serialization/dubbo-serialization-fastjson2/src/main/java/org/apache/dubbo/common/serialize/fastjson2/FastJson2ObjectOutput.java +++ b/dubbo-serialization/dubbo-serialization-fastjson2/src/main/java/org/apache/dubbo/common/serialize/fastjson2/FastJson2ObjectOutput.java @@ -98,6 +98,7 @@ public class FastJson2ObjectOutput implements ObjectOutput { updateClassLoaderIfNeed(); byte[] bytes = JSONB.toBytes(obj, JSONWriter.Feature.WriteClassName, JSONWriter.Feature.FieldBased, + JSONWriter.Feature.ErrorOnNoneSerializable, JSONWriter.Feature.ReferenceDetection, JSONWriter.Feature.WriteNulls, JSONWriter.Feature.NotWriteDefaultValue, diff --git a/dubbo-serialization/dubbo-serialization-fastjson2/src/main/java/org/apache/dubbo/common/serialize/fastjson2/FastJson2Serialization.java b/dubbo-serialization/dubbo-serialization-fastjson2/src/main/java/org/apache/dubbo/common/serialize/fastjson2/FastJson2Serialization.java index 4c20abcc8a..1e6b636787 100644 --- a/dubbo-serialization/dubbo-serialization-fastjson2/src/main/java/org/apache/dubbo/common/serialize/fastjson2/FastJson2Serialization.java +++ b/dubbo-serialization/dubbo-serialization-fastjson2/src/main/java/org/apache/dubbo/common/serialize/fastjson2/FastJson2Serialization.java @@ -39,8 +39,11 @@ public class FastJson2Serialization implements Serialization { private final Fastjson2CreatorManager fastjson2CreatorManager; + private final Fastjson2SecurityManager fastjson2SecurityManager; + public FastJson2Serialization(FrameworkModel frameworkModel) { this.fastjson2CreatorManager = frameworkModel.getBeanFactory().getBean(Fastjson2CreatorManager.class); + this.fastjson2SecurityManager = frameworkModel.getBeanFactory().getBean(Fastjson2SecurityManager.class); } @Override @@ -60,7 +63,7 @@ public class FastJson2Serialization implements Serialization { @Override public ObjectInput deserialize(URL url, InputStream input) throws IOException { - return new FastJson2ObjectInput(fastjson2CreatorManager, input); + return new FastJson2ObjectInput(fastjson2CreatorManager, fastjson2SecurityManager, input); } } diff --git a/dubbo-serialization/dubbo-serialization-fastjson2/src/main/java/org/apache/dubbo/common/serialize/fastjson2/Fastjson2ScopeModelInitializer.java b/dubbo-serialization/dubbo-serialization-fastjson2/src/main/java/org/apache/dubbo/common/serialize/fastjson2/Fastjson2ScopeModelInitializer.java index d9c9d25885..db256cce38 100644 --- a/dubbo-serialization/dubbo-serialization-fastjson2/src/main/java/org/apache/dubbo/common/serialize/fastjson2/Fastjson2ScopeModelInitializer.java +++ b/dubbo-serialization/dubbo-serialization-fastjson2/src/main/java/org/apache/dubbo/common/serialize/fastjson2/Fastjson2ScopeModelInitializer.java @@ -23,10 +23,12 @@ import org.apache.dubbo.rpc.model.ModuleModel; import org.apache.dubbo.rpc.model.ScopeModelInitializer; public class Fastjson2ScopeModelInitializer implements ScopeModelInitializer { + @Override public void initializeFrameworkModel(FrameworkModel frameworkModel) { ScopeBeanFactory beanFactory = frameworkModel.getBeanFactory(); beanFactory.registerBean(Fastjson2CreatorManager.class); + beanFactory.registerBean(Fastjson2SecurityManager.class); } @Override diff --git a/dubbo-serialization/dubbo-serialization-fastjson2/src/main/java/org/apache/dubbo/common/serialize/fastjson2/Fastjson2SecurityManager.java b/dubbo-serialization/dubbo-serialization-fastjson2/src/main/java/org/apache/dubbo/common/serialize/fastjson2/Fastjson2SecurityManager.java new file mode 100644 index 0000000000..e9334278c8 --- /dev/null +++ b/dubbo-serialization/dubbo-serialization-fastjson2/src/main/java/org/apache/dubbo/common/serialize/fastjson2/Fastjson2SecurityManager.java @@ -0,0 +1,128 @@ +/* + * 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.apache.dubbo.common.serialize.fastjson2; + +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.utils.AllowClassNotifyListener; +import org.apache.dubbo.common.utils.ConcurrentHashSet; +import org.apache.dubbo.common.utils.SerializeCheckStatus; +import org.apache.dubbo.common.utils.SerializeSecurityManager; +import org.apache.dubbo.rpc.model.FrameworkModel; + +import com.alibaba.fastjson2.filter.ContextAutoTypeBeforeHandler; +import com.alibaba.fastjson2.filter.Filter; +import com.alibaba.fastjson2.util.TypeUtils; + +import static com.alibaba.fastjson2.util.TypeUtils.loadClass; +import static org.apache.dubbo.common.constants.LoggerCodeConstants.PROTOCOL_UNTRUSTED_SERIALIZE_CLASS; +import static org.apache.dubbo.common.utils.SerializeCheckStatus.STRICT; + +public class Fastjson2SecurityManager implements AllowClassNotifyListener { + private Filter securityFilter = new Handler(AllowClassNotifyListener.DEFAULT_STATUS, new String[0]); + + private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(Fastjson2SecurityManager.class); + + private static final Set warnedClasses = new ConcurrentHashSet<>(1); + + public Fastjson2SecurityManager(FrameworkModel frameworkModel) { + SerializeSecurityManager securityManager = frameworkModel.getBeanFactory().getOrRegisterBean(SerializeSecurityManager.class); + securityManager.registerListener(this); + } + + public void notify(SerializeCheckStatus status, Set prefixList) { + this.securityFilter = new Handler(status, prefixList.toArray(new String[0])); + } + + public Filter getSecurityFilter() { + return securityFilter; + } + + public static class Handler extends ContextAutoTypeBeforeHandler { + final SerializeCheckStatus status; + final Map> classCache = new ConcurrentHashMap<>(16, 0.75f, 1); + + public Handler(SerializeCheckStatus status, String[] acceptNames) { + super(true, acceptNames); + this.status = status; + } + + @Override + public Class apply(String typeName, Class expectClass, long features) { + Class tryLoad = super.apply(typeName, expectClass, features); + + // 1. in allow list, return + if (tryLoad != null) { + return tryLoad; + } + + // 2. check if in strict mode + if (status == STRICT) { + String msg = "[Serialization Security] Serialized class " + typeName + " is not in allow list. " + + "Current mode is `STRICT`, will disallow to deserialize it by default. " + + "Please add it into security/serialize.allowlist or follow FAQ to configure it."; + if (warnedClasses.add(typeName)) { + logger.error(PROTOCOL_UNTRUSTED_SERIALIZE_CLASS, "", "", msg); + } + + return null; + } + + // 3. try load + Class localClass = loadClassDirectly(typeName); + if (localClass != null) { + if (status == SerializeCheckStatus.WARN && warnedClasses.add(typeName)) { + logger.error(PROTOCOL_UNTRUSTED_SERIALIZE_CLASS, "", "", + "[Serialization Security] Serialized class " + localClass.getName() + " is not in allow list. " + + "Current mode is `WARN`, will allow to deserialize it by default. " + + "Dubbo will set to `STRICT` mode by default in the future. " + + "Please add it into security/serialize.allowlist or follow FAQ to configure it."); + } + return localClass; + } + + // 4. class not found + return null; + } + + public Class loadClassDirectly(String typeName) { + Class clazz = classCache.get(typeName); + + if (clazz == null) { + clazz = TypeUtils.getMapping(typeName); + } + + if (clazz == null) { + clazz = loadClass(typeName); + } + + if (clazz != null) { + Class origin = classCache.putIfAbsent(typeName, clazz); + if (origin != null) { + clazz = origin; + } + } + + + return clazz; + } + } +} diff --git a/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2AllowClassManager.java b/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2AllowClassManager.java new file mode 100644 index 0000000000..a0564d4f66 --- /dev/null +++ b/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2AllowClassManager.java @@ -0,0 +1,120 @@ +/* + * 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.apache.dubbo.common.serialize.hessian2; + +import java.util.Arrays; +import java.util.Set; + +import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.utils.AllowClassNotifyListener; +import org.apache.dubbo.common.utils.ConcurrentHashSet; +import org.apache.dubbo.common.utils.SerializeCheckStatus; +import org.apache.dubbo.common.utils.SerializeSecurityManager; +import org.apache.dubbo.rpc.model.FrameworkModel; + +import static org.apache.dubbo.common.constants.LoggerCodeConstants.PROTOCOL_UNTRUSTED_SERIALIZE_CLASS; + +/** + * Inspired by Fastjson2 + * see com.alibaba.fastjson2.filter.ContextAutoTypeBeforeHandler#apply(java.lang.String, java.lang.Class, long) + */ +public class Hessian2AllowClassManager implements AllowClassNotifyListener { + private static final long MAGIC_HASH_CODE = 0xcbf29ce484222325L; + private static final long MAGIC_PRIME = 0x100000001b3L; + private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(Hessian2AllowClassManager.class); + private volatile SerializeCheckStatus checkStatus = AllowClassNotifyListener.DEFAULT_STATUS; + private static final Set warnedClasses = new ConcurrentHashSet<>(1); + private volatile long[] allowPrefixes = new long[0]; + + public Hessian2AllowClassManager(FrameworkModel frameworkModel) { + SerializeSecurityManager serializeSecurityManager = frameworkModel.getBeanFactory().getOrRegisterBean(SerializeSecurityManager.class); + serializeSecurityManager.registerListener(this); + } + + @Override + public void notify(SerializeCheckStatus status, Set prefixList) { + this.checkStatus = status; + long[] array = new long[prefixList.size()]; + + int index = 0; + for (String name : prefixList) { + if (name == null || name.isEmpty()) { + continue; + } + + long hashCode = MAGIC_HASH_CODE; + for (int j = 0; j < name.length(); ++j) { + char ch = name.charAt(j); + if (ch == '$') { + ch = '.'; + } + hashCode ^= ch; + hashCode *= MAGIC_PRIME; + } + + array[index++] = hashCode; + } + + if (index != array.length) { + array = Arrays.copyOf(array, index); + } + Arrays.sort(array); + this.allowPrefixes = array; + } + + public Class loadClass(ClassLoader classLoader, String className) throws ClassNotFoundException { + if (checkStatus == SerializeCheckStatus.DISABLED) { + return Class.forName(className, false, classLoader); + } + + long hash = MAGIC_HASH_CODE; + for (int i = 0, typeNameLength = className.length(); i < typeNameLength; ++i) { + char ch = className.charAt(i); + if (ch == '$') { + ch = '.'; + } + hash ^= ch; + hash *= MAGIC_PRIME; + + if (Arrays.binarySearch(allowPrefixes, hash) >= 0) { + return Class.forName(className, false, classLoader); + } + } + + if (checkStatus == SerializeCheckStatus.STRICT) { + String msg = "[Serialization Security] Serialized class " + className + " is not in allow list. " + + "Current mode is `STRICT`, will disallow to deserialize it by default. " + + "Please add it into security/serialize.allowlist or follow FAQ to configure it."; + if (warnedClasses.add(className)) { + logger.error(PROTOCOL_UNTRUSTED_SERIALIZE_CLASS, "", "", msg); + } + + throw new IllegalArgumentException(msg); + } else { + Class clazz = Class.forName(className, false, classLoader); + if (warnedClasses.add(className)) { + logger.error(PROTOCOL_UNTRUSTED_SERIALIZE_CLASS, "", "", + "[Serialization Security] Serialized class " + clazz.getName() + " is not in allow list. " + + "Current mode is `WARN`, will allow to deserialize it by default. " + + "Dubbo will set to `STRICT` mode by default in the future. " + + "Please add it into security/serialize.allowlist or follow FAQ to configure it."); + } + return clazz; + } + } +} diff --git a/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2ClassLoaderListener.java b/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2ClassLoaderListener.java new file mode 100644 index 0000000000..13b0b2462d --- /dev/null +++ b/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2ClassLoaderListener.java @@ -0,0 +1,33 @@ +/* + * 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.apache.dubbo.common.serialize.hessian2; + +import org.apache.dubbo.rpc.model.FrameworkModel; +import org.apache.dubbo.rpc.model.ScopeClassLoaderListener; + +public class Hessian2ClassLoaderListener implements ScopeClassLoaderListener { + @Override + public void onAddClassLoader(FrameworkModel scopeModel, ClassLoader classLoader) { + // noop + } + + @Override + public void onRemoveClassLoader(FrameworkModel scopeModel, ClassLoader classLoader) { + Hessian2FactoryManager hessian2FactoryManager = scopeModel.getBeanFactory().getBean(Hessian2FactoryManager.class); + hessian2FactoryManager.onRemoveClassLoader(classLoader); + } +} diff --git a/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2FactoryManager.java b/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2FactoryManager.java new file mode 100644 index 0000000000..a572925fef --- /dev/null +++ b/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2FactoryManager.java @@ -0,0 +1,110 @@ +/* + * 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.apache.dubbo.common.serialize.hessian2; + +import org.apache.dubbo.common.utils.StringUtils; +import org.apache.dubbo.rpc.model.FrameworkModel; + +import com.alibaba.com.caucho.hessian.io.SerializerFactory; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + + +public class Hessian2FactoryManager { + String WHITELIST = "dubbo.application.hessian2.whitelist"; + String ALLOW = "dubbo.application.hessian2.allow"; + String DENY = "dubbo.application.hessian2.deny"; + private volatile SerializerFactory SYSTEM_SERIALIZER_FACTORY; + private final Map CL_2_SERIALIZER_FACTORY = new ConcurrentHashMap<>(); + + private final Hessian2AllowClassManager hessian2AllowClassManager; + + public Hessian2FactoryManager(FrameworkModel frameworkModel) { + hessian2AllowClassManager = new Hessian2AllowClassManager(frameworkModel); + } + + public SerializerFactory getSerializerFactory(ClassLoader classLoader) { + if (classLoader == null) { + // system classloader + if (SYSTEM_SERIALIZER_FACTORY == null) { + synchronized (this) { + if (SYSTEM_SERIALIZER_FACTORY == null) { + SYSTEM_SERIALIZER_FACTORY = createSerializerFactory(); + } + } + } + return SYSTEM_SERIALIZER_FACTORY; + } + + if (!CL_2_SERIALIZER_FACTORY.containsKey(classLoader)) { + synchronized (this) { + if (!CL_2_SERIALIZER_FACTORY.containsKey(classLoader)) { + SerializerFactory serializerFactory = createSerializerFactory(); + CL_2_SERIALIZER_FACTORY.put(classLoader, serializerFactory); + return serializerFactory; + } + } + } + return CL_2_SERIALIZER_FACTORY.get(classLoader); + } + + private SerializerFactory createSerializerFactory() { + String whitelist = System.getProperty(WHITELIST); + if (StringUtils.isNotEmpty(whitelist)) { + return createWhiteListSerializerFactory(); + } + + return createDefaultSerializerFactory(); + } + + private SerializerFactory createDefaultSerializerFactory() { + Hessian2SerializerFactory hessian2SerializerFactory = new Hessian2SerializerFactory(hessian2AllowClassManager); + hessian2SerializerFactory.setAllowNonSerializable(Boolean.parseBoolean(System.getProperty("dubbo.hessian.allowNonSerializable", "false"))); + hessian2SerializerFactory.getClassFactory().allow("org.apache.dubbo.*"); + return hessian2SerializerFactory; + } + + public SerializerFactory createWhiteListSerializerFactory() { + SerializerFactory serializerFactory = new Hessian2SerializerFactory(hessian2AllowClassManager); + String whiteList = System.getProperty(WHITELIST); + if ("true".equals(whiteList)) { + serializerFactory.getClassFactory().setWhitelist(true); + String allowPattern = System.getProperty(ALLOW); + if (StringUtils.isNotEmpty(allowPattern)) { + for (String pattern : allowPattern.split(";")) { + serializerFactory.getClassFactory().allow(pattern); + } + } + } else { + serializerFactory.getClassFactory().setWhitelist(false); + String denyPattern = System.getProperty(DENY); + if (StringUtils.isNotEmpty(denyPattern)) { + for (String pattern : denyPattern.split(";")) { + serializerFactory.getClassFactory().deny(pattern); + } + } + } + serializerFactory.setAllowNonSerializable(Boolean.parseBoolean(System.getProperty("dubbo.hessian.allowNonSerializable", "false"))); + serializerFactory.getClassFactory().allow("org.apache.dubbo.*"); + return serializerFactory; + } + + public void onRemoveClassLoader(ClassLoader classLoader) { + CL_2_SERIALIZER_FACTORY.remove(classLoader); + } +} diff --git a/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2ObjectInput.java b/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2ObjectInput.java index 47aea6f2bc..f345621cc0 100644 --- a/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2ObjectInput.java +++ b/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2ObjectInput.java @@ -18,7 +18,7 @@ package org.apache.dubbo.common.serialize.hessian2; import org.apache.dubbo.common.serialize.Cleanable; import org.apache.dubbo.common.serialize.ObjectInput; -import org.apache.dubbo.common.serialize.hessian2.dubbo.Hessian2FactoryInitializer; +import org.apache.dubbo.rpc.model.FrameworkModel; import com.alibaba.com.caucho.hessian.io.Hessian2Input; @@ -31,12 +31,19 @@ import java.lang.reflect.Type; */ public class Hessian2ObjectInput implements ObjectInput, Cleanable { private final Hessian2Input mH2i; - private final Hessian2FactoryInitializer hessian2FactoryInitializer; + private final Hessian2FactoryManager hessian2FactoryManager; + @Deprecated public Hessian2ObjectInput(InputStream is) { mH2i = new Hessian2Input(is); - hessian2FactoryInitializer = Hessian2FactoryInitializer.getInstance(); - mH2i.setSerializerFactory(hessian2FactoryInitializer.getSerializerFactory()); + this.hessian2FactoryManager = FrameworkModel.defaultModel().getBeanFactory().getOrRegisterBean(Hessian2FactoryManager.class); + mH2i.setSerializerFactory(hessian2FactoryManager.getSerializerFactory(Thread.currentThread().getContextClassLoader())); + } + + public Hessian2ObjectInput(InputStream is, Hessian2FactoryManager hessian2FactoryManager) { + mH2i = new Hessian2Input(is); + this.hessian2FactoryManager = hessian2FactoryManager; + mH2i.setSerializerFactory(hessian2FactoryManager.getSerializerFactory(Thread.currentThread().getContextClassLoader())); } @Override @@ -87,7 +94,7 @@ public class Hessian2ObjectInput implements ObjectInput, Cleanable { @Override public Object readObject() throws IOException { if (!mH2i.getSerializerFactory().getClassLoader().equals(Thread.currentThread().getContextClassLoader())) { - mH2i.setSerializerFactory(hessian2FactoryInitializer.getSerializerFactory()); + mH2i.setSerializerFactory(hessian2FactoryManager.getSerializerFactory(Thread.currentThread().getContextClassLoader())); } return mH2i.readObject(); } @@ -97,7 +104,7 @@ public class Hessian2ObjectInput implements ObjectInput, Cleanable { public T readObject(Class cls) throws IOException, ClassNotFoundException { if (!mH2i.getSerializerFactory().getClassLoader().equals(Thread.currentThread().getContextClassLoader())) { - mH2i.setSerializerFactory(hessian2FactoryInitializer.getSerializerFactory()); + mH2i.setSerializerFactory(hessian2FactoryManager.getSerializerFactory(Thread.currentThread().getContextClassLoader())); } return (T) mH2i.readObject(cls); } @@ -105,7 +112,7 @@ public class Hessian2ObjectInput implements ObjectInput, Cleanable { @Override public T readObject(Class cls, Type type) throws IOException, ClassNotFoundException { if (!mH2i.getSerializerFactory().getClassLoader().equals(Thread.currentThread().getContextClassLoader())) { - mH2i.setSerializerFactory(hessian2FactoryInitializer.getSerializerFactory()); + mH2i.setSerializerFactory(hessian2FactoryManager.getSerializerFactory(Thread.currentThread().getContextClassLoader())); } return readObject(cls); } diff --git a/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2ObjectOutput.java b/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2ObjectOutput.java index 858ab57cb0..27c1ebd91d 100644 --- a/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2ObjectOutput.java +++ b/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2ObjectOutput.java @@ -18,7 +18,7 @@ package org.apache.dubbo.common.serialize.hessian2; import org.apache.dubbo.common.serialize.Cleanable; import org.apache.dubbo.common.serialize.ObjectOutput; -import org.apache.dubbo.common.serialize.hessian2.dubbo.Hessian2FactoryInitializer; +import org.apache.dubbo.rpc.model.FrameworkModel; import com.alibaba.com.caucho.hessian.io.Hessian2Output; @@ -32,9 +32,16 @@ public class Hessian2ObjectOutput implements ObjectOutput, Cleanable { private final Hessian2Output mH2o; + @Deprecated public Hessian2ObjectOutput(OutputStream os) { mH2o = new Hessian2Output(os); - mH2o.setSerializerFactory(Hessian2FactoryInitializer.getInstance().getSerializerFactory()); + Hessian2FactoryManager hessian2FactoryManager = FrameworkModel.defaultModel().getBeanFactory().getOrRegisterBean(Hessian2FactoryManager.class); + mH2o.setSerializerFactory(hessian2FactoryManager.getSerializerFactory(Thread.currentThread().getContextClassLoader())); + } + + public Hessian2ObjectOutput(OutputStream os, Hessian2FactoryManager hessian2FactoryManager) { + mH2o = new Hessian2Output(os); + mH2o.setSerializerFactory(hessian2FactoryManager.getSerializerFactory(Thread.currentThread().getContextClassLoader())); } @Override diff --git a/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2ScopeModelInitializer.java b/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2ScopeModelInitializer.java new file mode 100644 index 0000000000..578850905c --- /dev/null +++ b/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2ScopeModelInitializer.java @@ -0,0 +1,41 @@ +/* + * 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.apache.dubbo.common.serialize.hessian2; + +import org.apache.dubbo.common.beans.factory.ScopeBeanFactory; +import org.apache.dubbo.rpc.model.ApplicationModel; +import org.apache.dubbo.rpc.model.FrameworkModel; +import org.apache.dubbo.rpc.model.ModuleModel; +import org.apache.dubbo.rpc.model.ScopeModelInitializer; + +public class Hessian2ScopeModelInitializer implements ScopeModelInitializer { + @Override + public void initializeFrameworkModel(FrameworkModel frameworkModel) { + ScopeBeanFactory beanFactory = frameworkModel.getBeanFactory(); + beanFactory.registerBean(Hessian2FactoryManager.class); + } + + @Override + public void initializeApplicationModel(ApplicationModel applicationModel) { + + } + + @Override + public void initializeModuleModel(ModuleModel moduleModel) { + + } +} diff --git a/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2Serialization.java b/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2Serialization.java index 010a5b6f31..aebff2fbf5 100644 --- a/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2Serialization.java +++ b/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2Serialization.java @@ -20,6 +20,7 @@ import org.apache.dubbo.common.URL; import org.apache.dubbo.common.serialize.ObjectInput; import org.apache.dubbo.common.serialize.ObjectOutput; import org.apache.dubbo.common.serialize.Serialization; +import org.apache.dubbo.rpc.model.FrameworkModel; import java.io.IOException; import java.io.InputStream; @@ -36,6 +37,12 @@ import static org.apache.dubbo.common.serialize.Constants.HESSIAN2_SERIALIZATION */ public class Hessian2Serialization implements Serialization { + private final Hessian2FactoryManager hessian2FactoryManager; + + public Hessian2Serialization(FrameworkModel frameworkModel) { + hessian2FactoryManager = frameworkModel.getBeanFactory().getBean(Hessian2FactoryManager.class); + } + @Override public byte getContentTypeId() { return HESSIAN2_SERIALIZATION_ID; @@ -48,12 +55,12 @@ public class Hessian2Serialization implements Serialization { @Override public ObjectOutput serialize(URL url, OutputStream out) throws IOException { - return new Hessian2ObjectOutput(out); + return new Hessian2ObjectOutput(out, hessian2FactoryManager); } @Override public ObjectInput deserialize(URL url, InputStream is) throws IOException { - return new Hessian2ObjectInput(is); + return new Hessian2ObjectInput(is, hessian2FactoryManager); } } diff --git a/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2SerializerFactory.java b/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2SerializerFactory.java index 52cf50504d..e319cf7d61 100644 --- a/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2SerializerFactory.java +++ b/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2SerializerFactory.java @@ -20,7 +20,14 @@ import com.alibaba.com.caucho.hessian.io.SerializerFactory; public class Hessian2SerializerFactory extends SerializerFactory { - public Hessian2SerializerFactory() { + private Hessian2AllowClassManager hessian2AllowClassManager; + + public Hessian2SerializerFactory(Hessian2AllowClassManager hessian2AllowClassManager) { + this.hessian2AllowClassManager = hessian2AllowClassManager; } + @Override + public Class loadSerializedClass(String className) throws ClassNotFoundException { + return hessian2AllowClassManager.loadClass(getClassLoader(), className); + } } diff --git a/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/dubbo/AbstractHessian2FactoryInitializer.java b/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/dubbo/AbstractHessian2FactoryInitializer.java deleted file mode 100644 index 6bd18d22a1..0000000000 --- a/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/dubbo/AbstractHessian2FactoryInitializer.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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.apache.dubbo.common.serialize.hessian2.dubbo; - -import com.alibaba.com.caucho.hessian.io.SerializerFactory; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -public abstract class AbstractHessian2FactoryInitializer implements Hessian2FactoryInitializer { - private static final Map CL_2_SERIALIZER_FACTORY = new ConcurrentHashMap<>(); - private static volatile SerializerFactory SYSTEM_SERIALIZER_FACTORY; - - @Override - public SerializerFactory getSerializerFactory() { - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - // system classloader - if (SYSTEM_SERIALIZER_FACTORY == null) { - synchronized (AbstractHessian2FactoryInitializer.class) { - if (SYSTEM_SERIALIZER_FACTORY == null) { - SYSTEM_SERIALIZER_FACTORY = createSerializerFactory(); - } - } - } - return SYSTEM_SERIALIZER_FACTORY; - } - - if (!CL_2_SERIALIZER_FACTORY.containsKey(classLoader)) { - synchronized (AbstractHessian2FactoryInitializer.class) { - if (!CL_2_SERIALIZER_FACTORY.containsKey(classLoader)) { - SerializerFactory serializerFactory = createSerializerFactory(); - CL_2_SERIALIZER_FACTORY.put(classLoader, serializerFactory); - return serializerFactory; - } - } - } - return CL_2_SERIALIZER_FACTORY.get(classLoader); - } - - protected abstract SerializerFactory createSerializerFactory(); -} diff --git a/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/dubbo/Hessian2FactoryInitializer.java b/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/dubbo/Hessian2FactoryInitializer.java deleted file mode 100644 index 842888cf1b..0000000000 --- a/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/dubbo/Hessian2FactoryInitializer.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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.apache.dubbo.common.serialize.hessian2.dubbo; - -import org.apache.dubbo.common.extension.ExtensionLoader; -import org.apache.dubbo.common.extension.ExtensionScope; -import org.apache.dubbo.common.extension.SPI; -import org.apache.dubbo.common.utils.StringUtils; -import org.apache.dubbo.rpc.model.FrameworkModel; - -import com.alibaba.com.caucho.hessian.io.SerializerFactory; - -@SPI(value = "default", scope = ExtensionScope.FRAMEWORK) -public interface Hessian2FactoryInitializer { - String ALLOW = System.getProperty("dubbo.application.hessian2.allow"); - String DENY = System.getProperty("dubbo.application.hessian2.deny"); - String WHITELIST = System.getProperty("dubbo.application.hessian2.whitelist"); - - String ALLOW_NON_SERIALIZABLE = System.getProperty("dubbo.hessian.allowNonSerializable", "false"); - - SerializerFactory getSerializerFactory(); - - static Hessian2FactoryInitializer getInstance() { - ExtensionLoader loader = FrameworkModel.defaultModel().getExtensionLoader(Hessian2FactoryInitializer.class); - if (StringUtils.isNotEmpty(WHITELIST)) { - return loader.getExtension("whitelist"); - } - return loader.getDefaultExtension(); - } - -} diff --git a/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/dubbo/WhitelistHessian2FactoryInitializer.java b/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/dubbo/WhitelistHessian2FactoryInitializer.java deleted file mode 100644 index 53bcb0f0cb..0000000000 --- a/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/dubbo/WhitelistHessian2FactoryInitializer.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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.apache.dubbo.common.serialize.hessian2.dubbo; - -import org.apache.dubbo.common.serialize.hessian2.Hessian2SerializerFactory; -import org.apache.dubbo.common.utils.StringUtils; - -import com.alibaba.com.caucho.hessian.io.SerializerFactory; - -/** - * see https://github.com/ebourg/hessian/commit/cf851f5131707891e723f7f6a9718c2461aed826 - */ -public class WhitelistHessian2FactoryInitializer extends AbstractHessian2FactoryInitializer { - - @Override - public SerializerFactory createSerializerFactory() { - SerializerFactory serializerFactory = new Hessian2SerializerFactory(); - if ("true".equals(WHITELIST)) { - serializerFactory.getClassFactory().setWhitelist(true); - if (StringUtils.isNotEmpty(ALLOW)) { - for (String pattern : ALLOW.split(";")) { - serializerFactory.getClassFactory().allow(pattern); - } - } - } else { - serializerFactory.getClassFactory().setWhitelist(false); - if (StringUtils.isNotEmpty(DENY)) { - for (String pattern : DENY.split(";")) { - serializerFactory.getClassFactory().deny(pattern); - } - } - } - serializerFactory.setAllowNonSerializable(Boolean.parseBoolean(ALLOW_NON_SERIALIZABLE)); - serializerFactory.getClassFactory().allow("org.apache.dubbo.*"); - return serializerFactory; - } - -} diff --git a/dubbo-serialization/dubbo-serialization-hessian2/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.serialize.hessian2.dubbo.Hessian2FactoryInitializer b/dubbo-serialization/dubbo-serialization-hessian2/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.serialize.hessian2.dubbo.Hessian2FactoryInitializer deleted file mode 100644 index 460972e240..0000000000 --- a/dubbo-serialization/dubbo-serialization-hessian2/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.serialize.hessian2.dubbo.Hessian2FactoryInitializer +++ /dev/null @@ -1,2 +0,0 @@ -default=org.apache.dubbo.common.serialize.hessian2.dubbo.DefaultHessian2FactoryInitializer -whitelist=org.apache.dubbo.common.serialize.hessian2.dubbo.WhitelistHessian2FactoryInitializer \ No newline at end of file diff --git a/dubbo-serialization/dubbo-serialization-hessian2/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.model.ScopeModelInitializer b/dubbo-serialization/dubbo-serialization-hessian2/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.model.ScopeModelInitializer new file mode 100644 index 0000000000..8f25eb7be8 --- /dev/null +++ b/dubbo-serialization/dubbo-serialization-hessian2/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.model.ScopeModelInitializer @@ -0,0 +1 @@ +hessian2=org.apache.dubbo.common.serialize.hessian2.Hessian2ScopeModelInitializer diff --git a/dubbo-xds/pom.xml b/dubbo-xds/pom.xml index d162c2e163..913fe84187 100644 --- a/dubbo-xds/pom.xml +++ b/dubbo-xds/pom.xml @@ -31,6 +31,8 @@ The xDS Integration false + 3.18.3 + 1.41.0 @@ -50,16 +52,19 @@ io.grpc grpc-protobuf + ${grpc.version} io.grpc grpc-stub + ${grpc.version} io.grpc grpc-netty-shaded + ${grpc.version} @@ -67,9 +72,16 @@ api + + com.google.protobuf + protobuf-java + ${protobuf-java.version} + + com.google.protobuf protobuf-java-util + ${protobuf-java.version} @@ -101,9 +113,9 @@ protobuf-maven-plugin 0.6.1 - com.google.protobuf:protoc:3.12.0:exe:${os.detected.classifier} + com.google.protobuf:protoc:${protobuf-java.version}:exe:${os.detected.classifier} grpc-java - io.grpc:protoc-gen-grpc-java:1.31.1:exe:${os.detected.classifier} + io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier} diff --git a/pom.xml b/pom.xml index eccc9dc3b3..b1a0a9a040 100644 --- a/pom.xml +++ b/pom.xml @@ -885,4 +885,5 @@ +