您的位置:首页 > 编程语言 > Java开发

如何防止访问API的friendly方法

2012-10-10 22:47 309 查看
前几天在群里,一个前辈给我们出了一道题:

你现在要用第三方的一个jar,它提供了一个public方法给你用,但你反编译后发现,它有一个friendly级别的方法更符合你的要求,你想用那个方法,如何不修改原来的jar,来实现这个目的?

 

有朋友回答:搞了个跟他一样的包?即通过自己定义命名空间跟它一样的类就行了。这个其实容易实现的。

答对了,好,问题来了:如果你是这个jar的创建者,怎么防止别人这样的做法?

 

有朋友回答:把包封闭了,即,在打jar包时,在清单文件中添加Sealed: true来实现。但是包封闭只能避免更新这个包,也不能往这个包中添加类,但是如果用户定义与这个类相同的包,再调用friendly方法,还是不能避免上面说的问题。

 

解决方法:

可以通过获取当前调用这个friendly方法的类名或方法名,如果不是指定的类或方法则抛异常。

 

获取当前方法调用过程列表的方法,在JDK1.4中,Throwable类提供了一个getStackTrace方法来获得一个StackTraceElement对象数组;而在JDK1.5中在Thread类中提供了静态方法Thread.currentThread().getStackTrace()来获取StackTraceElement对象数组,而StackTraceElement能够获得类名、文件名、当前执行的代码行号、当前执行的方法名等信息。

具体测试代码如下:

package com.mmq.protecteapi;

import java.util.ArrayList;
import java.util.List;
/**
* @use
* @ProjectName stuff
* @Author <a href="mailto:mhmyqn@qq.com">mikan</a></br>
* @Date 2012-10-10 下午10:42:41 </br>
* @FullName com.mmq.protecteapi.A.java </br>
* @JDK 1.6.0 </br>
* @Version 1.0 </br>
*/
public class A {
void methodA() {
List<String> access = new ArrayList<String>();
access.add("com.mmq.protecteapi.A");
access.add("com.mmq.protecteapi.TestA");

//access.add("...");//add more

StackTraceElement[] stes = Thread.currentThread().getStackTrace();

System.out.println(stes[2].getClassName() + "." + stes[2].getMethodName() + "()");

String className = stes[2].getClassName();//为什么是第2个元素就不用说了吧

if(!access.contains(className)) {
throw new RuntimeException("Illegal Access...");
}

//do something...
}

public void methodB() {
methodA();
}

}

class TestA {

public void test() {
A a = new A();
a.methodB();
a.methodA();
}

}

class TestB {

public void test() {
A a = new A();
a.methodB();
a.methodA();
}

}

package com.mmq.protecteapi;

public class Test {

public static void main(String[] args) {
TestA a = new TestA();
a.test();

TestB b = new TestB();
b.test();
}

}

输出结果如下:
com.mmq.protecteapi.A.methodB()

com.mmq.protecteapi.TestA.test()

com.mmq.protecteapi.A.methodB()

com.mmq.protecteapi.TestB.test()

Exception in thread "main" java.lang.RuntimeException: Illegal Access...
at com.mmq.protecteapi.A.methodA(A.java:29)
at com.mmq.protecteapi.TestB.test(A.java:56)
at com.mmq.protecteapi.Test.main(Test.java:10)

思考:

1、方法既然设计成friendly的,那么同一个类、同一个包中的类都可以访问,那么如果需要调用这个friendly方法的类很多呢,一个一个添加是不是很暴力呢?就算不多,那么只要以后添加一个类,如果要访问这个方法,就得添加访问权限,那是不是很麻烦呢?(当然,可以把它设计成public的)

2、JDK可以避免用户定义以java开头的包,是通过类加载器来实现的,那这个问题是不是也通过类加载器来实现呢?

3、java提供的安全管理器(SecurityManager)是不是也可以实现呢?这个没有研究过,不敢乱说。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息