Skip to content
Permalink
Browse files Browse the repository at this point in the history
Added allowClass (closes #628)
  • Loading branch information
igr committed Aug 17, 2018
1 parent 63c4eb0 commit 9bffc39
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -24,6 +24,7 @@ All notable changes to Jodd project are documented here.
+ **mail** - added custom properties.
+ **json** - added `onValue` callback for JSON serializer.
+ **json** - added `excludeEmpty` flag for JSON serializer.
+ **json** - added `allowClass` for whitelisting class names.
+ **petite** - allow injection in the private fields of super types.


Expand Down
21 changes: 21 additions & 0 deletions jodd-json/src/main/java/jodd/json/JsonParser.java
Expand Up @@ -36,6 +36,7 @@
import jodd.util.UnsafeUtil;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
Expand Down Expand Up @@ -307,6 +308,26 @@ public JsonParser withClassMetadata(final boolean useMetadata) {
return this;
}

/**
* Adds a {@link jodd.util.Wildcard wildcard} pattern for white-listing classes.
* @see #setClassMetadataName(String)
*/
public JsonParser allowClass(final String classPattern) {
if (super.classnameWhitelist == null) {
super.classnameWhitelist = new ArrayList<>();
}
classnameWhitelist.add(classPattern);
return this;
}

/**
* Removes the whitelist of allowed classes.
* @see #setClassMetadataName(String)
*/
public JsonParser allowAllClasses() {
classnameWhitelist = null;
return this;
}

// ---------------------------------------------------------------- parse

Expand Down
1 change: 1 addition & 0 deletions jodd-json/src/main/java/jodd/json/JsonParserBase.java
Expand Up @@ -55,6 +55,7 @@ public abstract class JsonParserBase {

protected Supplier<Map> mapSupplier = HASMAP_SUPPLIER;
protected Supplier<List> listSupplier = ARRAYLIST_SUPPLIER;
protected List<String> classnameWhitelist;

/**
* Creates new instance of {@link jodd.json.MapToBean}.
Expand Down
14 changes: 14 additions & 0 deletions jodd-json/src/main/java/jodd/json/MapToBean.java
Expand Up @@ -32,6 +32,7 @@
import jodd.typeconverter.TypeConverterManager;
import jodd.util.ClassLoaderUtil;
import jodd.util.ClassUtil;
import jodd.util.Wildcard;

import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
Expand Down Expand Up @@ -69,6 +70,8 @@ public Object map2bean(final Map map, Class targetType) {
}
}
else {
checkClassName(jsonParser.classnameWhitelist, className);

try {
targetType = ClassLoaderUtil.loadClass(className);
} catch (ClassNotFoundException cnfex) {
Expand Down Expand Up @@ -145,6 +148,17 @@ else if (value instanceof Map) {
return target;
}

private void checkClassName(final List<String> classnameWhitelist, final String className) {
if (classnameWhitelist == null) {
return;
}
classnameWhitelist.forEach(pattern -> {
if (!Wildcard.equalsOrMatch(className, pattern)) {
throw new JsonException("Class can't be loaded as it is not whitelisted: " + className);
}
});
}

/**
* Converts type of all list elements to match the component type.
*/
Expand Down
32 changes: 32 additions & 0 deletions jodd-json/src/test/java/jodd/json/JSONDeserializerTest.java
Expand Up @@ -62,6 +62,7 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;

Expand Down Expand Up @@ -709,6 +710,37 @@ void testPoint() {
});
}

@Test
void testPointWithException() {
JsonParser.Defaults.classMetadataName = "__class";
JsonSerializer.Defaults.classMetadataName = "__class";

JsonParsers.forEachParser(jsonParser -> {
jsonParser.allowClass("notAllowed");
final String json = new JsonSerializer().serialize(new Point2D.Float(1.0f, 2.0f));
assertThrows(JsonException.class, () -> {
jsonParser.parse(json);
});
jsonParser.allowAllClasses();
});
}

@Test
void testPointWithoutExceptionWhitelisted() {
JsonParser.Defaults.classMetadataName = "__class";
JsonSerializer.Defaults.classMetadataName = "__class";

JsonParsers.forEachParser(jsonParser -> {
jsonParser.allowClass("*.Point?D*");
String json = new JsonSerializer().serialize(new Point2D.Float(1.0f, 2.0f));
Point2D.Float point = jsonParser.parse(json);
assertEquals(1.0f, point.x, DELTA);
assertEquals(2.0f, point.y, DELTA);
jsonParser.allowAllClasses();
});
}


@Test
void testUnixEpoch() {
JsonParsers.forEachParser(jsonParser -> {
Expand Down

0 comments on commit 9bffc39

Please sign in to comment.