diff --git a/pom.xml b/pom.xml index 2657b45..3b225a1 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.alipay.sofa hessian - 3.3.7 + 3.3.8 jar ${project.groupId}:${project.artifactId} @@ -70,6 +70,18 @@ 1.1-rev-1 provided + + org.slf4j + slf4j-api + 1.7.9 + provided + + + com.alipay.sofa.common + sofa-common-tools + 1.0.14 + provided + junit diff --git a/src/main/java/com/alipay/hessian/CallStackUtil.java b/src/main/java/com/alipay/hessian/CallStackUtil.java new file mode 100644 index 0000000..3610061 --- /dev/null +++ b/src/main/java/com/alipay/hessian/CallStackUtil.java @@ -0,0 +1,34 @@ +/* + * 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.alipay.hessian; + +/** + * + * @author ruoshan + * @version $Id: CallStackUtil.java, v 0.1 2019年02月13日 11:29 ruoshan Exp $ + */ +public class CallStackUtil { + + public static String getCurrentCallStack() { + StringBuilder msg = new StringBuilder(); + StackTraceElement[] elements = Thread.currentThread().getStackTrace(); + for (int index = 2; index < elements.length; index++) { + msg.append(elements[index].toString()).append("\n"); + } + return msg.toString(); + } +} \ No newline at end of file diff --git a/src/main/java/com/alipay/hessian/ClassNameResolver.java b/src/main/java/com/alipay/hessian/ClassNameResolver.java index ccd0f0f..041c31f 100644 --- a/src/main/java/com/alipay/hessian/ClassNameResolver.java +++ b/src/main/java/com/alipay/hessian/ClassNameResolver.java @@ -67,7 +67,7 @@ public int compare(ClassNameFilter o1, ClassNameFilter o2) { /** * 删除类名过滤器 - * + * * @param classNameFilter 类名过滤器 */ public void removeFilter(ClassNameFilter classNameFilter) { diff --git a/src/main/java/com/alipay/hessian/ClassNameResolverBuilder.java b/src/main/java/com/alipay/hessian/ClassNameResolverBuilder.java index 4c8bde3..39d35e9 100644 --- a/src/main/java/com/alipay/hessian/ClassNameResolverBuilder.java +++ b/src/main/java/com/alipay/hessian/ClassNameResolverBuilder.java @@ -34,7 +34,7 @@ public static ClassNameResolver buildDefault() { String enable = System.getProperty("serialize.blacklist.enable", "true"); if (Boolean.TRUE.toString().equalsIgnoreCase(enable)) { ClassNameResolver resolver = new ClassNameResolver(); - resolver.addFilter(new InternalNameBlackListFilter()); + resolver.addFilter(InternalNameBlackListFilter.Singleton()); return resolver; } return null; diff --git a/src/main/java/com/alipay/hessian/NameBlackListFilter.java b/src/main/java/com/alipay/hessian/NameBlackListFilter.java index c8de670..c84c72f 100644 --- a/src/main/java/com/alipay/hessian/NameBlackListFilter.java +++ b/src/main/java/com/alipay/hessian/NameBlackListFilter.java @@ -17,6 +17,7 @@ package com.alipay.hessian; import com.alipay.hessian.clhm.ConcurrentLinkedHashMap; +import org.slf4j.Logger; import java.io.IOException; import java.util.List; @@ -27,12 +28,36 @@ * * @author zhanggeng */ -public class NameBlackListFilter implements ClassNameFilter { +public abstract class NameBlackListFilter implements ClassNameFilter { + + private static Logger LOGGER = judgeLogger(); + + //do not change this + public static final String HESSIAN_SERIALIZE_LOG_NAME = "HessianSerializeLog"; + public static final String CONFIG_LOG_SPACE_NAME = "com.alipay.sofa.middleware.config"; + + private static Logger judgeLogger() { + + try { + NameBlackListFilter.class.getClassLoader().loadClass("com.alipay.sofa.common.log.LoggerSpaceManager"); + } catch (Throwable e) { + //do nothing + return null; + } + + return com.alipay.sofa.common.log.LoggerSpaceManager.getLoggerBySpace(HESSIAN_SERIALIZE_LOG_NAME, + CONFIG_LOG_SPACE_NAME); + } /** * 黑名单 包名前缀 */ - protected static List blackPrefixList; + protected List blackPrefixList; + + /** + * 全局黑名单 包名前缀, 优先级高于上者 + */ + protected static List addBlackPrefixList; /** * 类名是否在黑名单中结果缓存。{className:true/false} @@ -55,7 +80,7 @@ public NameBlackListFilter(List blackPrefixList) { * @param maxCacheSize 最大缓存大小 */ public NameBlackListFilter(List blackPrefixList, int maxCacheSize) { - NameBlackListFilter.blackPrefixList = blackPrefixList; + this.blackPrefixList = blackPrefixList; buildCache(blackPrefixList, maxCacheSize); } @@ -66,14 +91,13 @@ public NameBlackListFilter(List blackPrefixList, int maxCacheSize) { */ public static void buildCache(List blackPrefixList, int maxCacheSize) { if (blackPrefixList != null && !blackPrefixList.isEmpty()) { - NameBlackListFilter.blackPrefixList = blackPrefixList; int min = Math.min(256, maxCacheSize); int max = Math.min(10240, maxCacheSize); ConcurrentLinkedHashMap.Builder builder = new ConcurrentLinkedHashMap.Builder() .initialCapacity(min).maximumWeightedCapacity(max); - NameBlackListFilter.resultOfInBlackList = builder.build(); + resultOfInBlackList = builder.build(); } else { - NameBlackListFilter.resultOfInBlackList = null; + resultOfInBlackList = null; } } @@ -85,12 +109,32 @@ public String resolve(String className) throws IOException { if (blackPrefixList == null || resultOfInBlackList == null) { return className; } + final String monitorKey = "@" + className; + Boolean monitorResult = resultOfInBlackList.get(monitorKey); + if (monitorResult == null) { + monitorResult = inBlackList(monitorKey); + resultOfInBlackList.putIfAbsent(monitorKey, monitorResult); + } + + if (monitorResult && LOGGER != null) { + LOGGER.info(String.format( + "[status] %s, [class] %s, [rule] %s, [callStack] %s", + "watch", className, monitorKey, CallStackUtil + .getCurrentCallStack())); + + } + Boolean result = resultOfInBlackList.get(className); if (result == null) { result = inBlackList(className); resultOfInBlackList.putIfAbsent(className, result); } - if (result) { + if (result && LOGGER != null) { + LOGGER.info(String.format( + "[status] %s, [class] %s, [rule] %s, [callStack] %s", + "control", className, className, CallStackUtil + .getCurrentCallStack())); + throw new IOException("Class " + className + " is in blacklist. "); } else { return className; @@ -101,14 +145,29 @@ public String resolve(String className) throws IOException { * 检测类名是否不在黑名单中 * * @param className - * @return 是否在黑名单中 + * @return */ protected boolean inBlackList(String className) { - for (String prefix : blackPrefixList) { - if (className.startsWith(prefix)) { - return Boolean.TRUE; + + //动态推送不允许推空,推送一个白名单的值即可 + if (addBlackPrefixList != null && addBlackPrefixList.size() != 0) { + for (String prefix : addBlackPrefixList) { + if (className.startsWith(prefix)) { + return Boolean.TRUE; + } + } + } else { + for (String prefix : blackPrefixList) { + if (className.startsWith(prefix)) { + return Boolean.TRUE; + } } } + return Boolean.FALSE; } + + public static void setAddBlackPrefixList(List addBlackPrefixList) { + NameBlackListFilter.addBlackPrefixList = addBlackPrefixList; + } } diff --git a/src/main/java/com/alipay/hessian/NameBlackListFilterManager.java b/src/main/java/com/alipay/hessian/NameBlackListFilterManager.java index 1879e77..b10a3a9 100644 --- a/src/main/java/com/alipay/hessian/NameBlackListFilterManager.java +++ b/src/main/java/com/alipay/hessian/NameBlackListFilterManager.java @@ -25,6 +25,6 @@ public class NameBlackListFilterManager { */ public static void rebuildBlackList(List blackList) { - NameBlackListFilter.buildCache(blackList, 4096); + NameBlackListFilter.setAddBlackPrefixList(blackList); } } diff --git a/src/main/java/com/alipay/hessian/internal/InternalNameBlackListFilter.java b/src/main/java/com/alipay/hessian/internal/InternalNameBlackListFilter.java index d08daa1..d599ff5 100644 --- a/src/main/java/com/alipay/hessian/internal/InternalNameBlackListFilter.java +++ b/src/main/java/com/alipay/hessian/internal/InternalNameBlackListFilter.java @@ -103,4 +103,21 @@ static boolean isBlank(String cs) { } return true; } + + /** + * 单例 + */ + private volatile static InternalNameBlackListFilter instance; + + public static InternalNameBlackListFilter Singleton() { + if (instance == null) { //step1 + synchronized (InternalNameBlackListFilter.class) { //step2 + if (instance == null) { //step3 + instance = new InternalNameBlackListFilter(); //step4 + } + } + } + + return instance; + } } diff --git a/src/test/java/com/alipay/stc/ArrayInjectTest.java b/src/test/java/com/alipay/stc/ArrayInjectTest.java index 3e537f7..e103f88 100644 --- a/src/test/java/com/alipay/stc/ArrayInjectTest.java +++ b/src/test/java/com/alipay/stc/ArrayInjectTest.java @@ -40,10 +40,9 @@ public void testHessian2Array() throws IOException { ByteArrayInputStream input = new ByteArrayInputStream(bs, 0, bs.length); Hessian2Input hin = new Hessian2Input(input); hin.setSerializerFactory(factory); - try { hin.readObject(); - Assert.fail(); + Assert.fail("should be intercepted"); } catch (Exception e) { Assert.assertTrue(e instanceof IOException); } diff --git a/tools/ci/.travis.settings.xml b/tools/ci/.travis.settings.xml index ddd1cfe..07e3075 100644 --- a/tools/ci/.travis.settings.xml +++ b/tools/ci/.travis.settings.xml @@ -14,7 +14,7 @@ central Central Repository - http://repo1.maven.org/maven2 + https://repo1.maven.org/maven2 true always @@ -108,7 +108,7 @@ central - http://repo1.maven.org/maven2 + https://repo1.maven.org/maven2 true always