Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/hessian optimize for blacklist #54

Merged
merged 8 commits into from
Apr 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

<groupId>com.alipay.sofa</groupId>
<artifactId>hessian</artifactId>
<version>3.3.7</version>
<version>3.3.8</version>
<packaging>jar</packaging>

<name>${project.groupId}:${project.artifactId}</name>
Expand Down Expand Up @@ -70,6 +70,18 @@
<version>1.1-rev-1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.9</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.alipay.sofa.common</groupId>
<artifactId>sofa-common-tools</artifactId>
<version>1.0.14</version>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>junit</groupId>
Expand Down
34 changes: 34 additions & 0 deletions src/main/java/com/alipay/hessian/CallStackUtil.java
Original file line number Diff line number Diff line change
@@ -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();
}
}
2 changes: 1 addition & 1 deletion src/main/java/com/alipay/hessian/ClassNameResolver.java
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public int compare(ClassNameFilter o1, ClassNameFilter o2) {

/**
* 删除类名过滤器
*
*
* @param classNameFilter 类名过滤器
*/
public void removeFilter(ClassNameFilter classNameFilter) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
81 changes: 70 additions & 11 deletions src/main/java/com/alipay/hessian/NameBlackListFilter.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -27,12 +28,36 @@
*
* @author <a href="mailto:zhanggeng.zg@antfin.com">zhanggeng</a>
*/
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<String> blackPrefixList;
protected List<String> blackPrefixList;

/**
* 全局黑名单 包名前缀, 优先级高于上者
*/
protected static List<String> addBlackPrefixList;

/**
* 类名是否在黑名单中结果缓存。{className:true/false}
Expand All @@ -55,7 +80,7 @@ public NameBlackListFilter(List<String> blackPrefixList) {
* @param maxCacheSize 最大缓存大小
*/
public NameBlackListFilter(List<String> blackPrefixList, int maxCacheSize) {
NameBlackListFilter.blackPrefixList = blackPrefixList;
this.blackPrefixList = blackPrefixList;
buildCache(blackPrefixList, maxCacheSize);
}

Expand All @@ -66,14 +91,13 @@ public NameBlackListFilter(List<String> blackPrefixList, int maxCacheSize) {
*/
public static void buildCache(List<String> 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<String, Boolean> builder = new ConcurrentLinkedHashMap.Builder<String, Boolean>()
.initialCapacity(min).maximumWeightedCapacity(max);
NameBlackListFilter.resultOfInBlackList = builder.build();
resultOfInBlackList = builder.build();
} else {
NameBlackListFilter.resultOfInBlackList = null;
resultOfInBlackList = null;
}
}

Expand All @@ -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;
Expand All @@ -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<String> addBlackPrefixList) {
NameBlackListFilter.addBlackPrefixList = addBlackPrefixList;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@ public class NameBlackListFilterManager {
*/
public static void rebuildBlackList(List<String> blackList) {

NameBlackListFilter.buildCache(blackList, 4096);
NameBlackListFilter.setAddBlackPrefixList(blackList);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
3 changes: 1 addition & 2 deletions src/test/java/com/alipay/stc/ArrayInjectTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
4 changes: 2 additions & 2 deletions tools/ci/.travis.settings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<repository>
<id>central</id>
<name>Central Repository</name>
<url>http://repo1.maven.org/maven2</url>
<url>https://repo1.maven.org/maven2</url>
<releases>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
Expand Down Expand Up @@ -108,7 +108,7 @@
<pluginRepository>
<id>central</id>
<!-- specify repo1 which support http -->
<url>http://repo1.maven.org/maven2</url>
<url>https://repo1.maven.org/maven2</url>
<releases>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
Expand Down