如何防止仅对某些字段进行反射?

How to prevent reflection only for some fields?

我们都知道java中字段和方法的关键字“private”只在构建时起作用,而在运行时需要3行才能绕过。 我正在为某些东西制作一个插件系统,这些插件是在我的进程中加载​​的 jar。所以,我需要一种方法来防止插件访问我游戏的某些字段,这些字段不能从外部访问。问题是“private”关键字没用,Reflection.registerFieldsToFilter 也没用。 我尝试过的:

making the field private (field.setAccessible() bypasses)

doing Reflection.registerFieldsToFilter (Class.getDeclaredFields0() bypasses)

那我该怎么做才能让一些 fields/methods/classes 真正私有化?

如果 SecurityManager 不存在,则无法保证将您的字段设为私有。

准确地说,如果SecurityManager撤销一个以下权限,则您的字段是安全的:

  • accessDeclaredMembers:通过反射
  • 提供对class成员的访问
  • suppressAccessChecks:提供对 class
  • 的非 public 成员的访问

供参考,https://docs.oracle.com/javase/7/docs/technotes/guides/security/permissions.html

如果你的SecurityManager

  1. 授予上述权限和getProtectionDomain,您可以调用Reflection.registerFieldsToFilter通过修改过滤器映射来保护您的字段。然后,您还可以通过取消过滤 java.lang.System.security 字段并使用反射访问它来替换 SecurityManager。但是,这不是一种合适的方法。如果一个插件将其字段添加到过滤器映射并修改 SecurityManager 使得过滤器映射不再可访问,则下一个插件不能重复相同的过程。此外,这违背了安全管理器和访问修饰符的目的。

  2. 授予除getProtectionDomain之外的上述三个权限,您不能过滤您的字段,而其他人可以使用反射访问您的字段。

  3. 不授予 accessDeclaredMemberssuppressAccessChecks,那么您的字段是安全的,不会通过反射访问。

方法一:设置SecurityManager

相反,您可以 SecurityManager 撤销上面的部分/所有权限,并将 getter 和 setter 添加到您希望其他插件可以访问的字段中。如果您的插件不负责设置合适的SecurityManager,您可以在您的插件的信息页面上发布通知,提醒用户使用其他可信赖的方法设置SecurityManager

方法二:混淆闭源

既然反射在序列化中被广泛使用,另一种方法是不将您的插件开源,并对您的代码进行混淆,这样开发人员将很难追踪到您一直在谈论的领域。

方法 3:使其成为 Web 服务,但其可行性取决于您的插件的功能。

方法 4:拒绝模块或包内的反射访问 当包没有修饰符 opens 时,它不能通过模块外部的反射访问,类似地对于没有 open 的模块。您还可以定义 to modulename ,其中只有该模块可以通过反射访问您的包:

module example {
    opens package.one //can be accessed via reflection
    exports package.two //can only be accessed during compilation i.e. no reflection
}

我写了一篇绕过SecurityManager的文章,上面授予了3个权限,虽然有点过时了。 https://github.com/Bernard2518141184/Disable-Security-Manager