1.ReflectPermission介绍
ReflectPermission这个类通常是在反射中用来权限校验的,下面这张表格列举了各种权限及授予权限后带来的风险:
权限名称 | 授权范围 | 授权后带来的风险 |
| 可以屏蔽java原本对字段和方法的各种访问权限校验;不仅可以访问公共成员,还能访问default、protected以及private成员。 | 可能被恶意代码访问到正常情况下无法得到的信息和方法 |
| 可以在代理类实现的非公共接口所在的包中创建一个代理对象 | 恶意代码可能借此访问到原本无法方法访问的类,以及那些处于系统保护域内的动态类。从而破坏系统的安全性 |
里面就两个构造方法:
public ReflectPermission(String name) {
super(name);
}
public ReflectPermission(String name, String actions) {
super(name, actions);
}
可以看到,构造方法其实调用的是父类BasicPermission的构造方法,我们去看看BasicPermission的构造方法做了些什么。
public BasicPermission(String name) {
super(name);
init(name);
}
super(name)是给本地字段name赋值,重点是init(name),来看下具体代码:
/**
* initialize a BasicPermission object. Common to all constructors.
*/
private void init(String name) {
if (name == null)
throw new NullPointerException("name can't be null");
int len = name.length();
if (len == 0) {
throw new IllegalArgumentException("name can't be empty");
}
char last = name.charAt(len - 1);
// Is wildcard or ends with ".*"?
if (last == '*' && (len == 1 || name.charAt(len - 2) == '.')) {
wildcard = true;
if (len == 1) {
path = "";
} else {
path = name.substring(0, len - 1);
}
} else {
if (name.equals("exitVM")) {
wildcard = true;
path = "exitVM.";
exitVM = true;
} else {
path = name;
}
}
}
代码不难看懂,第一种情况如果name是*或者以.*结尾说明是通配符模式,分别给wildcard和path赋值;第二种情况如果name等于“exitVM”就给wildcard、path、exitVM分别赋值;其他情况直接让path等于name。
2.ReflectPermission使用场景
这个类我们最常使用的场景是,在反射时候如果想使用某个非公有方法或者非公有构造器,需要先设置其可以访问,这时就要用到java.lang.reflect.AccessibleObject的setAccessible方法:
public void setAccessible(boolean flag) throws SecurityException {
SecurityManager sm = System.getSecurityManager();
if (sm != null) sm.checkPermission(ACCESS_PERMISSION);
setAccessible0(this, flag);
}
这里的ACCESS_PERMISSION是一个私有的静态常量,实际上就是我们上面提到的suppressAccessChecks类型的RelectPermission。
static final private java.security.Permission ACCESS_PERMISSION =
new ReflectPermission("suppressAccessChecks");
从上面的代码中我们可以看到涉及了SecurityManager,通过名字我们就可以知道这是安全管理器,具体什么是安全管理器可以看下一节介绍。然后是setAccessible0(this,flag)方法中会把本地属性override设置成true。