add ValidateObjectInputStream

This commit is contained in:
Looly
2020-04-03 12:13:56 +08:00
parent f2b44605d0
commit 3921a568dd
8 changed files with 299 additions and 17 deletions

View File

@@ -2348,7 +2348,9 @@ public class CollUtil {
* @param <V> Value类型
* @param map {@link Map}
* @param kvConsumer {@link KVConsumer} 遍历的每条数据处理器
* @deprecated JDK8+中使用map.forEach
*/
@Deprecated
public static <K, V> void forEach(Map<K, V> map, KVConsumer<K, V> kvConsumer) {
int index = 0;
for (Entry<K, V> entry : map.entrySet()) {
@@ -2527,6 +2529,18 @@ public class CollUtil {
return Collections.min(coll);
}
/**
* 转为只读集合
*
* @param <T> 元素类型
* @param c 集合
* @return 只读集合
* @since 5.2.6
*/
public static <T> Collection<T> unmodifiable(Collection<? extends T> c) {
return Collections.unmodifiableCollection(c);
}
// ---------------------------------------------------------------------------------------------- Interface start
/**

View File

@@ -444,4 +444,16 @@ public class ListUtil {
}
return Convert.convert(int[].class, indexList);
}
/**
* 将对应List转换为不可修改的List
*
* @param list Map
* @param <T> 元素类型
* @return 不修改Map
* @since 5.2.6
*/
public static <T> List<T> unmodifiable(List<T> list) {
return Collections.unmodifiableList(list);
}
}

View File

@@ -636,24 +636,38 @@ public class IoUtil {
}
/**
* 从流中读取内容,读到输出流中
* 从流中读取对象,即对象的反序列化
*
* @param <T> 读取对象的类型
* @param in 输入流
* @return 输出流
* @throws IORuntimeException IO异常
* @throws UtilException ClassNotFoundException包装
* @deprecated 由于存在对象反序列化漏洞风险,请使用{@link #readObj(InputStream, Class)}
*/
@Deprecated
public static <T> T readObj(InputStream in) throws IORuntimeException, UtilException {
return readObj(in, null);
}
/**
* 从流中读取对象,即对象的反序列化,读取后不关闭流
*
* @param <T> 读取对象的类型
* @param in 输入流
* @return 输出流
* @throws IORuntimeException IO异常
* @throws UtilException ClassNotFoundException包装
*/
public static <T> T readObj(InputStream in, Class<T> clazz) throws IORuntimeException, UtilException {
if (in == null) {
throw new IllegalArgumentException("The InputStream must not be null");
}
ObjectInputStream ois;
try {
ois = new ObjectInputStream(in);
@SuppressWarnings("unchecked") // may fail with CCE if serialised form is incorrect
final T obj = (T) ois.readObject();
return obj;
ois = new ValidateObjectInputStream(in, clazz);
//noinspection unchecked
return (T) ois.readObject();
} catch (IOException e) {
throw new IORuntimeException(e);
} catch (ClassNotFoundException e) {

View File

@@ -0,0 +1,53 @@
package cn.hutool.core.io;
import java.io.IOException;
import java.io.InputStream;
import java.io.InvalidClassException;
import java.io.ObjectInputStream;
import java.io.ObjectStreamClass;
/**
* 带有类验证的对象流,用于避免反序列化漏洞<br>
* 详细见https://xz.aliyun.com/t/41/
*
* @author looly
* @since 5.2.6
*/
public class ValidateObjectInputStream extends ObjectInputStream {
private Class<?> acceptClass;
/**
* 构造
*
* @param inputStream 流
* @param acceptClass 接受的类
* @throws IOException IO异常
*/
public ValidateObjectInputStream(InputStream inputStream, Class<?> acceptClass) throws IOException {
super(inputStream);
this.acceptClass = acceptClass;
}
/**
* 接受反序列化的类,用于反序列化验证
*
* @param acceptClass 接受反序列化的类
*/
public void accept(Class<?> acceptClass) {
this.acceptClass = acceptClass;
}
/**
* 只允许反序列化SerialObject class
*/
@Override
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
if (null != this.acceptClass && false == desc.getName().equals(acceptClass.getName())) {
throw new InvalidClassException(
"Unauthorized deserialization attempt",
desc.getName());
}
return super.resolveClass(desc);
}
}

View File

@@ -560,7 +560,7 @@ public class MapUtil {
public static <K, V> String join(Map<K, V> map, String separator, String keyValueSeparator, boolean isIgnoreNull, String... otherParams) {
final StringBuilder strBuilder = StrUtil.builder();
boolean isFirst = true;
if(isNotEmpty(map)){
if (isNotEmpty(map)) {
for (Entry<K, V> entry : map.entrySet()) {
if (false == isIgnoreNull || entry.getKey() != null && entry.getValue() != null) {
if (isFirst) {
@@ -733,7 +733,7 @@ public class MapUtil {
* @since 4.0.1
*/
public static <K, V> TreeMap<K, V> sort(Map<K, V> map, Comparator<? super K> comparator) {
if(null == map){
if (null == map) {
return null;
}
@@ -777,6 +777,19 @@ public class MapUtil {
return new MapWrapper<>(map);
}
/**
* 将对应Map转换为不可修改的Map
*
* @param map Map
* @param <K> 键类型
* @param <V> 值类型
* @return 不修改Map
* @since 5.2.6
*/
public static <K, V> Map<K, V> unmodifiable(Map<K, V> map) {
return Collections.unmodifiableMap(map);
}
// ----------------------------------------------------------------------------------------------- builder
/**