Java 基于类的模拟
类是否可以模拟其身份?例如,类A尝试访问类B方法。类B方法使用getClass.getName尝试检查类A以确保它是谁。模拟能发生吗?e、 类C模拟类A以通过getclass。getName类B用于检查 如果类B想要实现getClass.getName以进行对下面的示例方法有效的检查,那么如何在下面的示例代码中正确地实现它Java 基于类的模拟,java,class,impersonation,Java,Class,Impersonation,类是否可以模拟其身份?例如,类A尝试访问类B方法。类B方法使用getClass.getName尝试检查类A以确保它是谁。模拟能发生吗?e、 类C模拟类A以通过getclass。getName类B用于检查 如果类B想要实现getClass.getName以进行对下面的示例方法有效的检查,那么如何在下面的示例代码中正确地实现它 public byte[] getStoragePrivateKey(String application) { if (application.getClass()
public byte[] getStoragePrivateKey(String application) {
if (application.getClass().getName().equals("correctClass") {
// Allow access to Private Key.
} else {
// Access denied
}
}
上面的示例模拟了系统中的插件小程序试图访问系统中的内部密钥服务器数据库。您可以使用多个类加载器执行此操作。每个类都可以有一个名称相同但不同的类 但是,如果可以,我建议您使用反射来绕过此安全性 编写验证的一种更简单的方法是
if (application.getClass() == CorrectClass.class) {
实现验证的一种改进方法是使用
StackTraceElement[] stes = Thread.currentThread().getStackTrace();
if (stes[0].getClassName().equals("correctClass") {
这确保调用方来自正确的类名。它仍然可以被类装入器欺骗
sun.misc.Unsafe类使用类似于后者的内容来保护getUnsafe方法。标准的解决方法是去做
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
Unsafe unafe = theUnsafe.get(null);
如果您想知道为什么不安全被保护,以及为什么您可能想要获得访问权限,请查看方法列表
编辑:Unsafe.getUnsafe过去是受保护的,但在最新的源代码中似乎不再存在。可能是因为支票很容易被绕过 您可以使用多个类加载器来实现这一点。每个类都可以有一个名称相同但不同的类 但是,如果可以,我建议您使用反射来绕过此安全性 编写验证的一种更简单的方法是
if (application.getClass() == CorrectClass.class) {
实现验证的一种改进方法是使用
StackTraceElement[] stes = Thread.currentThread().getStackTrace();
if (stes[0].getClassName().equals("correctClass") {
这确保调用方来自正确的类名。它仍然可以被类装入器欺骗
sun.misc.Unsafe类使用类似于后者的内容来保护getUnsafe方法。标准的解决方法是去做
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
Unsafe unafe = theUnsafe.get(null);
如果您想知道为什么不安全被保护,以及为什么您可能想要获得访问权限,请查看方法列表
编辑:Unsafe.getUnsafe过去是受保护的,但在最新的源代码中似乎不再存在。可能是因为支票很容易被绕过 这行不通:
在您的示例中,application.getClass.getName将始终返回java.lang.String,因为您正在获取应用程序参数的类型
此外,在Java中,被调用的方法无法从调用它的位置找到类型,因此,您可能应该检查您的设计,实现其他类型的访问控制
编辑:让我根据您的代码添加一个示例,说明如何尝试检查调用器的类型,以及如何避免来自其他源的调用:
//Change the String for an Object, to allow the invoker pass a
//reference to itself
public byte[] getStoragePrivateKey(Object application) {
if (application.getClass().getName().equals("correctClass") {
// Allow access to Private Key.
} else {
// Access denied
}
}
从引用类型A中,调用可以是:
B b=new B();
byte[] key=b.getStoragePrivateKey(this);
从C模拟程序类调用它将失败,因为这是C.class实例:
B b=new B();
byte[] key=b.getStoragePrivateKey(this);
但是,避免验证非常简单:
B b=new B();
A a=new A();
byte[] key=b.getStoragePrivateKey(a);
这行不通:
在您的示例中,application.getClass.getName将始终返回java.lang.String,因为您正在获取应用程序参数的类型
此外,在Java中,被调用的方法无法从调用它的位置找到类型,因此,您可能应该检查您的设计,实现其他类型的访问控制
编辑:让我根据您的代码添加一个示例,说明如何尝试检查调用器的类型,以及如何避免来自其他源的调用:
//Change the String for an Object, to allow the invoker pass a
//reference to itself
public byte[] getStoragePrivateKey(Object application) {
if (application.getClass().getName().equals("correctClass") {
// Allow access to Private Key.
} else {
// Access denied
}
}
从引用类型A中,调用可以是:
B b=new B();
byte[] key=b.getStoragePrivateKey(this);
从C模拟程序类调用它将失败,因为这是C.class实例:
B b=new B();
byte[] key=b.getStoragePrivateKey(this);
但是,避免验证非常简单:
B b=new B();
A a=new A();
byte[] key=b.getStoragePrivateKey(a);
尽管您不能加载伪java.*类,或者通常不能加载父类加载程序加载的任何类。@Tom Hawtin,除非违反许可协议。但这在技术上是可能的。我写过关于使用自压缩字符串的文章,这是一个运行时,它报告对gc的调用位置等。Terracotta在运行时更改java.*类,Profiler向任何类注入代码以获取附加信息。但是,我不相信他们加载了多个副本。@Peter Lawrey您可以用-Xbootclasspath或类似的内容替换Java库的某些部分,但您不应该使用类加载器来实现它。@Tom Hawtin,我想您是对的,但我知道你可以通过插装来完成。@Peter Lawrey Java代理与使用-Xbootclasspath非常相似。尽管你不能加载伪Java.*类,或者通常是由父类加载器加载的任何类。@Tom Hawtin,除非违反许可协议。但这在技术上是可能的。我写过关于使用自压缩字符串的文章,这是一个运行时,它报告对gc的调用位置等。Terracotta在运行时更改java.*类,分析器向任何类注入代码以获得addit
国际信息。但是,我不相信他们加载了多个副本。@Peter Lawrey您可以用-Xbootclasspath或类似的内容替换Java库的某些部分,但您不应该使用类加载器来实现它。@Tom Hawtin,我想您是对的,但我知道你可以通过插装来实现。@Peter Lawrey Java代理与使用-Xbootclasspath非常相似。你想实现什么?有很多方法可以在Java中实现安全性,最简单的是安全策略。我想先看一下,因为它们允许您以一种健壮的方式提供访问控制—您想要实现什么?有很多方法可以在Java中实现安全性,最简单的是安全策略。我先看一下,因为它们允许您以一种健壮的方式提供访问控制-