示例中需要在eclipse中创建2个project:ServiceCentre和TestService
java.policy
permission java.io.FilePermission " c:/TestService-1.0.jar " , " read " ;
permission java.lang.RuntimePermission " createClassLoader " ;
} ;
grant codeBase " file:/c:/TestService-1.0.jar " {
permission java.io.FilePermission " C:/text.txt " , " read " ;
} ;
Project - ServiceCentre
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
/**
* @author Donf Yang
*/
public class ServiceCentreMain {
public void loadService() {
URL[] urls;
try {
urls = new URL[] { new URL( " file:c:/TestService-1.0.jar " ) } ;
URLClassLoader ll = new URLClassLoader(urls);
final Class a = ll.loadClass( " test.TestService " );
Object o = a.newInstance();
Method m = a.getMethod( " doService " , null );
m.invoke(o, null );
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* @param args
*/
public static void main(String[] args) {
ServiceCentreMain s = new ServiceCentreMain();
s.loadService();
}
}
Project - TestService
将TestService打包,放到C盘
import java.io.FilePermission;
import java.security.AccessController;
import java.security.Permission;
/**
* @author Donf Yang
*
*/
public class TestService {
public void doService() {
doFileOperation();
}
private void doFileOperation() {
Permission perm = new FilePermission( " C:/text.txt " , " read " );
AccessController.checkPermission(perm);
System.out.println( " TestService has permission " );
}
}
运行这个例子的时候,会出现权限错误,把doService()修改一下,就可以顺利通过
// doFileOperation();
AccessController.doPrivileged( new PrivilegedAction() {
public Object run() {
doFileOperation();
return null ;
}
} );
}
在这个例子中AccessControlContext的stack顺序为
2. file:/D:/Workspaces/ExchangeConnect_V2_Trunk_Maven_workspace/ServiceCentre/bin/*
1 . file:/c:/TestService-1.0.jar
2没有权限,1有权限,使用doPrivileged后,不检查2
看一下java.security.AccessController的JavaDoc:
其中提到的no further checking is done的意思是指stack中的checking
加入一个TestService2,文件操作在1,stack为(1,2,3为checking顺序)
3 . file:/D:/Workspaces/ExchangeConnect_V2_Trunk_Maven_workspace/ServiceCentre/bin/*
2 . file:/c:/TestService-1.0.jar
1. file:/c:/TestService2-1.0.jar
checking顺序为 1->2->3
如果doPrivileged是在2中调用,那么1,2需要具有权限,3不再进行检查
如果doPrivileged是在1中调用,那么1需要具有权限,2,3不再进行检查
总结:
1. 这里容易理解错误的地方是checking顺序,例如一个调用链 MethodA->MethodB->MethodC(这里的3个方法需要在3个不同的ProtectionDomain 中),doPrivileged在MethodB中,很容易理解成检查A,B而不检查C,实际上stack中检查顺序为C->B->A,也就 是检查C,B而不检查A
2. ServiceCentre不需要太多权限,而Service就需要使用doPrivileged来避免受到ServiceCentre的权限限制(如果service有足够的权限),Equinox中有很多这样的例子(Equinox扮演Service的角色)。