Java安全管理器完全禁用反射

12

我在Stackoverflow上看了很多关于这个问题的问题,但是没有找到解决方案或答案。如果已经有解决方案,如果有人能给一个提示,我会非常感激...

我的问题/疑问是是否有可能完全禁用不可信代码的反射?像getDeclaredMethods()这样的函数(请参见test.java)。我已经有了一个Java安全管理器,如果代码尝试写入/读取等操作,则会引发安全异常...

如果有可能,能否有人展示一下如何做到?

Bruno

test.java

TestClass cls = new TestClass();
Class c = cls.getClass();

// returns the array of Method objects 
Method[] m = c.getDeclaredMethods();
for(int i = 0; i < m.length; i++) {
   System.out.println("method = " + m[i].toString());
}
3个回答

6

所以我没有直接使用checkPermission()解决问题。我的解决方法是检查是否访问了java.lang.reflect包。

@Override
public void checkPackageAccess(String pkg){

    // don't allow the use of the reflection package
    if(pkg.equals("java.lang.reflect")){
        throw new SecurityException("Reflection is not allowed!");
    }
}

我可能错了,但我相当确定 if (pkg.startsWith("java.lang.reflect")){ 会更安全。 - edoardottt

5

扩展您的SecurityManager,并检查ReflectPermission和RuntimePermission。然后,您需要决定调用者是否具有Reflection权限:

@Override
public void checkPermission(Permission perm) {
  if (perm instanceof ReflectPermission) {
    // called for Method.setAccessible(true)
    // determine whether caller is permitted    using getClassContext()
  }
  if (perm instanceof RuntimePermission) {
    if (perm.implies(new RuntimePermission("accessDeclaredMembers"))) {
      // called for Class.getDeclardFields()
      System.out.println("getDeclaredFields() called");
    }
}

我复制了你的代码,并添加了throw new SecurityException(...),但异常并没有被抛出...甚至函数都没有被调用... - Bruno
是的,getDeclaredMethods()方法并没有调用SecurityManager,但是如果您想通过Method.setAccessible(true)访问私有/受保护的方法,则会调用SecurityManager - Stefan
1
我更新了关于 getDeclaredXYZ() 检查的答案。希望能有所帮助。 - Stefan
它没有正常工作,我不知道为什么,但checkPermission函数甚至都没有被调用... - Bruno
政策是全局的还是可以针对特定的包进行设置?例如,在具有插件的情况下,如何仅限制插件JAR。因为我们可能会有其他依赖于反射的库(ORM,Gson等)。 - TheRealChx101

1
只要我们不提供安全管理器,类的私有成员就可以被访问。要访问类的私有成员,您应该设置setAccessible(true),这将允许您访问私有成员。为限制访问私有成员,请在您的不可变类构造函数中保留以下代码行。
System.setSecurityManager(new SecurityManager());
当您尝试设置setAccessible(true)时,这将抛出AccessControlException。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接