Enhance serializable check option (#11460)

* Enhance serializable check option

* Fix
This commit is contained in:
Albumen Kevin 2023-02-14 15:15:51 +08:00 committed by GitHub
parent b21baffa8c
commit 5a27cb55b0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 100 additions and 30 deletions

View File

@ -201,4 +201,8 @@ public class DefaultSerializeClassChecker implements AllowClassNotifyListener {
public static DefaultSerializeClassChecker getInstance() {
return FrameworkModel.defaultModel().getBeanFactory().getBean(DefaultSerializeClassChecker.class);
}
public boolean isCheckSerializable() {
return checkSerializable;
}
}

View File

@ -16,15 +16,15 @@
*/
package org.apache.dubbo.common.serialize.fastjson2;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;
import org.apache.dubbo.common.serialize.ObjectInput;
import com.alibaba.fastjson2.JSONB;
import com.alibaba.fastjson2.JSONReader;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;
/**
* FastJson object input implementation
*/
@ -111,11 +111,19 @@ 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, fastjson2SecurityManager.getSecurityFilter(),
JSONReader.Feature.UseDefaultConstructorAsPossible,
JSONReader.Feature.ErrorOnNoneSerializable,
JSONReader.Feature.UseNativeObject,
JSONReader.Feature.FieldBased);
Fastjson2SecurityManager.Handler securityFilter = fastjson2SecurityManager.getSecurityFilter();
if (securityFilter.isCheckSerializable()) {
return (T) JSONB.parseObject(bytes, Object.class, securityFilter,
JSONReader.Feature.UseDefaultConstructorAsPossible,
JSONReader.Feature.ErrorOnNoneSerializable,
JSONReader.Feature.UseNativeObject,
JSONReader.Feature.FieldBased);
} else {
return (T) JSONB.parseObject(bytes, Object.class, securityFilter,
JSONReader.Feature.UseDefaultConstructorAsPossible,
JSONReader.Feature.UseNativeObject,
JSONReader.Feature.FieldBased);
}
}
@Override
@ -128,11 +136,19 @@ 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, fastjson2SecurityManager.getSecurityFilter(),
JSONReader.Feature.UseDefaultConstructorAsPossible,
JSONReader.Feature.ErrorOnNoneSerializable,
JSONReader.Feature.UseNativeObject,
JSONReader.Feature.FieldBased);
Fastjson2SecurityManager.Handler securityFilter = fastjson2SecurityManager.getSecurityFilter();
if (securityFilter.isCheckSerializable()) {
return (T) JSONB.parseObject(bytes, Object.class, securityFilter,
JSONReader.Feature.UseDefaultConstructorAsPossible,
JSONReader.Feature.ErrorOnNoneSerializable,
JSONReader.Feature.UseNativeObject,
JSONReader.Feature.FieldBased);
} else {
return (T) JSONB.parseObject(bytes, Object.class, securityFilter,
JSONReader.Feature.UseDefaultConstructorAsPossible,
JSONReader.Feature.UseNativeObject,
JSONReader.Feature.FieldBased);
}
}
private void updateClassLoaderIfNeed() {

View File

@ -16,14 +16,14 @@
*/
package org.apache.dubbo.common.serialize.fastjson2;
import java.io.IOException;
import java.io.OutputStream;
import org.apache.dubbo.common.serialize.ObjectOutput;
import com.alibaba.fastjson2.JSONB;
import com.alibaba.fastjson2.JSONWriter;
import java.io.IOException;
import java.io.OutputStream;
/**
* FastJson object output implementation
*/
@ -31,11 +31,16 @@ public class FastJson2ObjectOutput implements ObjectOutput {
private final Fastjson2CreatorManager fastjson2CreatorManager;
private final Fastjson2SecurityManager fastjson2SecurityManager;
private volatile ClassLoader classLoader;
private final OutputStream os;
public FastJson2ObjectOutput(Fastjson2CreatorManager fastjson2CreatorManager, OutputStream out) {
public FastJson2ObjectOutput(Fastjson2CreatorManager fastjson2CreatorManager,
Fastjson2SecurityManager fastjson2SecurityManager,
OutputStream out) {
this.fastjson2CreatorManager = fastjson2CreatorManager;
this.fastjson2SecurityManager = fastjson2SecurityManager;
this.classLoader = Thread.currentThread().getContextClassLoader();
this.os = out;
fastjson2CreatorManager.setCreator(classLoader);
@ -96,14 +101,25 @@ public class FastJson2ObjectOutput implements ObjectOutput {
@Override
public void writeObject(Object obj) throws IOException {
updateClassLoaderIfNeed();
byte[] bytes = JSONB.toBytes(obj, JSONWriter.Feature.WriteClassName,
JSONWriter.Feature.FieldBased,
JSONWriter.Feature.ErrorOnNoneSerializable,
JSONWriter.Feature.ReferenceDetection,
JSONWriter.Feature.WriteNulls,
JSONWriter.Feature.NotWriteDefaultValue,
JSONWriter.Feature.NotWriteHashMapArrayListClassName,
JSONWriter.Feature.WriteNameAsSymbol);
byte[] bytes;
if (fastjson2SecurityManager.getSecurityFilter().isCheckSerializable()) {
bytes = JSONB.toBytes(obj, JSONWriter.Feature.WriteClassName,
JSONWriter.Feature.FieldBased,
JSONWriter.Feature.ErrorOnNoneSerializable,
JSONWriter.Feature.ReferenceDetection,
JSONWriter.Feature.WriteNulls,
JSONWriter.Feature.NotWriteDefaultValue,
JSONWriter.Feature.NotWriteHashMapArrayListClassName,
JSONWriter.Feature.WriteNameAsSymbol);
} else {
bytes = JSONB.toBytes(obj, JSONWriter.Feature.WriteClassName,
JSONWriter.Feature.FieldBased,
JSONWriter.Feature.ReferenceDetection,
JSONWriter.Feature.WriteNulls,
JSONWriter.Feature.NotWriteDefaultValue,
JSONWriter.Feature.NotWriteHashMapArrayListClassName,
JSONWriter.Feature.WriteNameAsSymbol);
}
writeLength(bytes.length);
os.write(bytes);
os.flush();

View File

@ -54,8 +54,12 @@ public class FastJson2Serialization implements Serialization {
.map(URL::getOrDefaultFrameworkModel)
.orElse(FrameworkModel.defaultModel())
.getBeanFactory().getBean(Fastjson2CreatorManager.class);
Fastjson2SecurityManager fastjson2SecurityManager = Optional.ofNullable(url)
.map(URL::getOrDefaultFrameworkModel)
.orElse(FrameworkModel.defaultModel())
.getBeanFactory().getBean(Fastjson2SecurityManager.class);
return new FastJson2ObjectOutput(fastjson2CreatorManager, output);
return new FastJson2ObjectOutput(fastjson2CreatorManager, fastjson2SecurityManager, output);
}
@Override

View File

@ -29,7 +29,6 @@ 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;
@ -37,7 +36,7 @@ import static org.apache.dubbo.common.constants.LoggerCodeConstants.PROTOCOL_UNT
import static org.apache.dubbo.common.utils.SerializeCheckStatus.STRICT;
public class Fastjson2SecurityManager implements AllowClassNotifyListener {
private volatile Filter securityFilter;
private volatile Handler securityFilter;
private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(Fastjson2SecurityManager.class);
@ -77,7 +76,7 @@ public class Fastjson2SecurityManager implements AllowClassNotifyListener {
}
public Filter getSecurityFilter() {
public Handler getSecurityFilter() {
return securityFilter;
}

View File

@ -16,8 +16,14 @@
*/
package org.apache.dubbo.common.serialize.hessian2;
import java.io.Serializable;
import org.apache.dubbo.common.utils.DefaultSerializeClassChecker;
import com.alibaba.com.caucho.hessian.io.Deserializer;
import com.alibaba.com.caucho.hessian.io.JavaDeserializer;
import com.alibaba.com.caucho.hessian.io.JavaSerializer;
import com.alibaba.com.caucho.hessian.io.Serializer;
import com.alibaba.com.caucho.hessian.io.SerializerFactory;
public class Hessian2SerializerFactory extends SerializerFactory {
@ -32,4 +38,29 @@ public class Hessian2SerializerFactory extends SerializerFactory {
public Class<?> loadSerializedClass(String className) throws ClassNotFoundException {
return defaultSerializeClassChecker.loadClass(getClassLoader(), className);
}
@Override
protected Serializer getDefaultSerializer(Class cl) {
if (_defaultSerializer != null)
return _defaultSerializer;
if (!Serializable.class.isAssignableFrom(cl)
&& !isAllowNonSerializable()
&& !defaultSerializeClassChecker.isCheckSerializable()) {
throw new IllegalStateException("Serialized class " + cl.getName() + " must implement java.io.Serializable");
}
return new JavaSerializer(cl, getClassLoader());
}
@Override
protected Deserializer getDefaultDeserializer(Class cl) {
if (!Serializable.class.isAssignableFrom(cl)
&& !isAllowNonSerializable()
&& !defaultSerializeClassChecker.isCheckSerializable()) {
throw new IllegalStateException("Serialized class " + cl.getName() + " must implement java.io.Serializable");
}
return new JavaDeserializer(cl);
}
}