java中操作系统的名称(不是“os.name”)

我想知道如何掌握jvm运行的那种操作系统。 它也必须是“安全的”,因此System.getProperty("os.name")实际上不是一个选项,因为它可以通过-D指令轻易绕过。

通过“安全”,我的意思是不容置疑。 它适用于桌面应用程序。 用户总是可以对代码进行反混淆,反编译,编辑和重新编译,但这比将-D传递给jvm要困难得多。 我们想要修补不平凡,而不是不可能(因为那是不可能做到的)。

首先,保护代码不被其运行时环境任意操纵是不可能的。 但是为了使它至少难以欺骗你的支票,最好的选择可能是某种基于文件系统的操作系统指纹识别 。

File.listRoots()是你的出发点; 在类Unix系统上,它将返回一个包含/ etc,/ usr等特征目录的根。在Windows上,它将返回多个结果,但AFAIK OS安装驱动器不一定是C:并且特征目录不同Windows版本和语言环境 – 小心不要假设每个人都运行英文版的Vista。

你可以投入大量的工作来识别不同版本的Windows和Linux,以及BSD或MacOS – 一旦它们在那里,从编译后的代码中删除支票可能会花费很少的工作。

系统属性是我所知道的获取操作系统信息的唯一方法。 甚至OperatingSystemMXBean也从os.X系统属性中获取其值。

如果有人可以修改你的应用程序的启动方式,那么你遇到的问题比os.name是正确的要大。

但是,如果您担心在应用程序运行时设置该属性的恶意代码,则可以使用Java安全管理器确保安全地保护属性。

你为什么担心这个? 如果最终用户愚蠢到捣乱os。*属性,为什么不让应用程序爆炸呢?

话虽如此,这些可能适合您的目的

 //can be defeated by adding com.apple.eawt.Application to the classpath public boolean isMac() { try { Class.forName("com.apple.eawt.Application"); return true; } catch(Exception e) { return false; } } //can be defeated by creating a cmd.exe in PATH public boolean isWin() { try{ Runtime.getRuntime().exec( new String[]{"cmd.exe","/C","dir"} ).waitFor(); return true; } catch (Exception e) { return false; } } public boolean isLinux() { if(isMac()) return false; try{ Runtime.getRuntime().exec( new String[]{"sh","-c","ls"} ).waitFor(); return true; } catch (Exception e) { return false; } } 

您可以通过Runtime类(exec方法)运行外部cmd(如“ver”)来获取os的版本(如果在windows中)或“uname -a”

Apache commons-vfs抽象了一些处理,因此您可以处理Os和OsFamily 。 但是在内部,它仍然使用System.getProperty(..)来获取值。 我不知道JVM获取这些值的任何其他方式。

如果有人能够更改传递给JVM的属性,那么处理它们时遇到的问题比它们更改奇数属性要大。

你能详细说明安全意味着什么。 从谁安全?

你可以使用exec来尝试运行一些你可以期望在一个操作系统或另一个操作系统上存在的无害程序 – 例如windows的“c:\ windows \ system \ dir.exe”和* nix的“/ bin / ls” – – 看看他们是否成功运行或轰炸。 但当然有人知道你正在这样做,并试图破坏它,他们可以用这些名字创建可执行文件。

你究竟想从中获得什么安全呢? 如果有人故意搞砸你的应用程序的启动,然后它因为你试图运行不存在的命令而爆炸,那么不会有适当的反应,“如果你的脚受伤了,就停止自己在脚下射击。” 如果你所做的只是运行操作系统命令,大概是用户可以访问你应用程序之外的那些命令,所以我不知道操作系统的谎言会如何危及安全性。

除了使用您提到的属性之外,VM中没有公共API。

我希望,由于Java应该是安全的,因此VM会忽略从命令行覆盖这些值的任何尝试,但事实并非如此。

您可能会尝试不允许写入这些值的SecurityManager,但我的猜测是,那么该值将为空(因为VM也无法更改它)。

您还可以通过System.getenv()检查环境变量,但用户也可以在启动之前自由修改这些变量。 只是不太容易(至少在Windows上)修改变量作为命令行的一部分来启动应用程序。

如果安全性是您的主要目标,您可能想尝试添加一些JNI。 首先,如果您尝试在Linux或OS X中加载DLL,我敢打赌它会崩溃/不加载。 其次,从该DLL可以调用操作系统的API,因此您不仅限于Java环境提供的内容。

我同意jni / jna是一个更好的选择。 只需调用类似Native.loadLibrary(“myLib”)的东西,在Windows上它将加载myLib.dll,在linux – myLib.so上。 这是最安全的方式,一个人不能搞砸它。 将所有特定于os的代码放在库中,并将编译后的版本保存在jar中。

现代Linux系统有一个特殊的文件/proc/version ,它提供了内核版本ID。 因此,如果该文件存在匹配合适的模式(例如,从单词Linux ),则增加了在Linux计算机上运行的可能性。 相反,如果它不存在或与该模式不匹配,您可以确定您没有在Linux上运行。

为什么不组合以下内容并使用它进行插值,这种方式可能很难绕过。

 public class OpertingSystemInfo { public static void main(String[] args) { String nameOS = "os.name"; String versionOS = "os.version"; String architectureOS = "os.arch"; System.out.println("\n The information about OS"); System.out.println("\nName of the OS: " + System.getProperty(nameOS)); System.out.println("Version of the OS: " + System.getProperty(versionOS)); System.out.println("Architecture of THe OS: " + System.getProperty(architectureOS)); } }