如何通过反射防止访问?

13

Java文档提到使用f.setAccessible(true)方法可以违反封装原则。

但是,如果我编写了一个具有完全安全性的类,例如带有私有变量的类,如何防止它被反射访问呢?

例如,我有一个带有完全保护的实例变量的类:

public final class Immutable {
    private final int someVal;

    public Immutable(int someVal) {
        this.someVal = someVal;
    }

    public int getVal() {
        return someVal;
    }
}

但我可以使用反射来修改那个实例变量,就像这样:

public class Tester {
    public static void main(String[] args)
            throws NoSuchFieldException, SecurityException,
            IllegalArgumentException, IllegalAccessException {

        Immutable i = new Immutable(10);

        // output 10
        System.out.println(i.getVal());

        Field f = i.getClass().getDeclaredField("someVal");
        f.setAccessible(true);
        f.set(i, 11);

        // output is 11 which implies some value modified
        System.out.println(i.getVal());
    }
}

在我的代码中,我如何防止使用反射改变一个不可变类?


1
请查看 SecurityManager - Sotirios Delimanolis
2
除非你允许陌生人向你正在创建的某个东西添加插件,否则你不需要担心这个问题。你想要制作什么应用程序? - satnam
如果你担心安全问题,仅仅限制反射访问并不足够值得。如果不受信任的代码可以读取、写入或删除计算机上的任何文件,那么它无法访问一个对象属性对于计算机的所有者来说并没有太大帮助。 - bdsl
2个回答

10

扩展SecurityManager类并重写此方法以限制反射访问。

@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!");
         }
     }

1
缺少 super.checkPackageAccess(pkg); 这非常重要!!! - sampopes
我感觉有些东西不对劲。首先,您没有说明如何处理扩展的SecurityManager。其次,如果客户端使用自己的SecurityManager来执行与您相同的操作,那么这会阻止您的代码吗? - barneypitt
您需要在启动方法中添加System.setSecurityManager(new SecurityManagerExt());。对于SpringBoot,您可以将此添加到您的主方法中。 - undefined

10

JVM内置了安全机制,可通过Java安全策略文件定义代码的限制。 Java安全管理器使用Java安全策略文件来执行授予类的一组权限。这些权限允许在JVM实例中运行的指定类允许或不允许某些运行时操作。

如果启用Java安全管理器但未指定安全策略文件,则Java安全管理器将使用$JAVA_HOME/jre/lib/security目录中的java.security和java.policy文件定义的默认安全策略。

在此处找到如何定义您的策略文件http://docs.oracle.com/javase/7/docs/technotes/guides/security/PolicyFiles.html


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