【问题标题】:Detect if Java application was run as a Windows admin检测 Java 应用程序是否以 Windows 管理员身份运行
【发布时间】:2011-05-20 00:27:03
【问题描述】:

我有一个 Java 应用程序。无论如何我可以判断该进程是否在 Windows 7 上以管理员权限运行。

【问题讨论】:

  • 我在 Linux 中测试了我的答案。它可能不依赖于操作系统,但我不知道。

标签: java windows admin privileges


【解决方案1】:

Java 运行时环境中没有这样的工具,但可能在依赖于平台的本机例程中。请注意,通常最好的确定方法是实际尝试去做,看看它是否失败。

【讨论】:

    【解决方案2】:

    仅通过尝试需要此类访问的操作(如绑定低编号端口,或打开已知受保护的文件)。

    【讨论】:

    • 谢谢。这对我有用。我试图在程序文件中创建一个测试文件并捕获 IOException (Access is Denied)... new File(System.getenv("programfiles")+"/test.tst").createNewFile()
    【解决方案3】:

    或者你可以这样做:

    System.getenv().get("USER")

    并查看哪个用户启动了该过程。

    当我以我的身份运行它时,我得到“goran”,当我使用 sudo 运行它时,我得到“root”。在 Linux 上工作。 可能需要什么。

    【讨论】:

    • 嗯,这很有趣,让我试试这个,看看它在 Windows 上的作用。如果它说“管理员”,这将起作用。
    • 请发布您的结果。我真的很想知道这是否与操作系统无关
    • 在 Windows 7 上,如果我运行此代码,我会得到一个空值。但是,如果我运行 System.getProperty("user.name"),我会得到我的用户名。但是,这仍然不能说明我是否是管理员。
    • 有趣。尝试获取所有属性:System.out.println(System.getenv()); 也许,还有别的东西。
    • 也可以试试:System.out.println(System.getProperties());
    【解决方案4】:

    我在网上找到了这个代码 sn-p,我认为它会为你完成这项工作。

    public static boolean isAdmin() {
        String groups[] = (new com.sun.security.auth.module.NTSystem()).getGroupIDs();
        for (String group : groups) {
            if (group.equals("S-1-5-32-544"))
                return true;
        }
        return false;
    }
    

    它仅适用于 Windows,并内置于核心 Java 包中。我刚刚测试了这段代码,它确实有效。这让我感到惊讶,但确实如此。

    SID S-1-5-32-544 是 Windows 操作系统中管理员组的 ID。

    Here is the link 了解其工作原理的更多详细信息。

    【讨论】:

    • 不错的 S-1-5-32-544。我早该想到的。
    • ... 由于私有类,仅适用于 Sun JVM。
    • 请注意,此 sn-p 测试活动用户是否为管理员,而不是用户是否已将应用程序作为提升的进程启动!
    • 如果应用程序以管理员帐户的正常权限运行,这将不起作用。仍然返回 true...
    • 此代码可能仅适用于 Oracle JRE,不保证适用于 JRE 的任何更新:oracle.com/technetwork/java/faq-sun-packages-142232.html
    【解决方案5】:

    答案中标记为最佳的方法对我来说效果很好,直到我不得不在 Linux 机器上在 Jenkins 中构建代码。 com.sun.security.auth.module.NTSystem() 在那里不可用,使用 sun 包通常被认为是一种不好的做法: link

    【讨论】:

    • 从您的 Windows 机器中获取“rt.jar”。将它添加到 Linux 机器上的类路径中。然后在你的应用程序中有代码,可以查看它是否是 Windows PC,执行接受的答案,如果是 Linux,运行这个问题的 Linux 答案。想到的第一个解决方案。对我来说,我只需要在 Windows 上这样做,所以我没有这个问题。它是 Java 做的很糟糕的事情之一。只是一个旁注,您应该将其添加为评论。
    • 感谢有关 rt.jar 的提示!我会试一试。 PS:我知道,这应该是一个评论,但不幸的是,由于stackoverflow授予权限的方式有点奇怪,以我目前的声誉,我只能评论我自己的答案/问题=)
    【解决方案6】:

    我找到了一个似乎与平台无关的不同解决方案。它尝试编写系统首选项。如果失败,用户可能不是管理员。

    正如Tomáš Zato 建议的那样,您可能希望抑制由此方法引起的错误消息。你可以通过设置System.err来做到这一点:

    import java.io.OutputStream;
    import java.io.PrintStream;
    import java.util.prefs.Preferences;
    
    import static java.lang.System.setErr;
    import static java.util.prefs.Preferences.systemRoot;
    
    public class AdministratorChecker
    {
        public static final boolean IS_RUNNING_AS_ADMINISTRATOR;
    
        static
        {
            IS_RUNNING_AS_ADMINISTRATOR = isRunningAsAdministrator();
        }
    
        private static boolean isRunningAsAdministrator()
        {
            Preferences preferences = systemRoot();
    
            synchronized (System.err)
            {
                setErr(new PrintStream(new OutputStream()
                {
                    @Override
                    public void write(int b)
                    {
                    }
                }));
    
                try
                {
                    preferences.put("foo", "bar"); // SecurityException on Windows
                    preferences.remove("foo");
                    preferences.flush(); // BackingStoreException on Linux
                    return true;
                } catch (Exception exception)
                {
                    return false;
                } finally
                {
                    setErr(System.err);
                }
            }
        }
    }
    

    【讨论】:

    • 很好,但我建议您将状态缓存到私有静态变量中。它不会在程序的一个实例中改变。
    • 还有一件事——函数不断产生输出,例如Kvě 07, 2015 1:49:14 ODP. java.util.prefs.WindowsPreferences <init> WARNING: Could not open/create prefs root node Software\JavaSoft\Prefs at root 0x80000002. Windows RegCreateKeyEx(...) returned error code 5. 是否可以抑制这些?
    • @TomášZato 我改进了我的答案
    • 请注意,由于System.setErr(null),答案中的第二个代码块会抛出NullPointerException。要解决此问题,请改用虚拟输出流:System.setErr(new PrintStream(new OutputStream() { @Override public void write(int i) throws IOException { } }));
    • 如果其他线程也没有同步到System.err,则synchronized(systemErr) 行无效。
    【解决方案7】:

    这是一个在 Windows 10 上的解决方案,我猜它在其他 Windows 操作系统上也能正常运行。

    public static boolean isAdmin() {
        try {
            ProcessBuilder processBuilder = new ProcessBuilder("cmd.exe");
            Process process = processBuilder.start();
            PrintStream printStream = new PrintStream(process.getOutputStream(), true);
            Scanner scanner = new Scanner(process.getInputStream());
            printStream.println("@echo off");
            printStream.println(">nul 2>&1 \"%SYSTEMROOT%\\system32\\cacls.exe\" \"%SYSTEMROOT%\\system32\\config\\system\"");
            printStream.println("echo %errorlevel%");
    
            boolean printedErrorlevel = false;
            while (true) {
                String nextLine = scanner.nextLine();
                if (printedErrorlevel) {
                    int errorlevel = Integer.parseInt(nextLine);
                    return errorlevel == 0;
                } else if (nextLine.equals("echo %errorlevel%")) {
                    printedErrorlevel = true;
                }
            }
        } catch (IOException e) {
            return false;
        }
    }
    

    【讨论】:

      【解决方案8】:

      以下代码适合我

      命令提示符命令

      net user
      

      Java 代码

      public static  boolean isAdmin() {
              StringBuilder outputbuilder = new StringBuilder();
          try {
              ProcessBuilder builder = new ProcessBuilder(
                      "cmd.exe","/c" ,"net user");
              builder.redirectErrorStream(true);
              Process p = builder.start();
              BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()));
              String line;
              while (true) {
                  line = r.readLine();
                  if (line == null) { break; }
                  outputbuilder.append(line);
              }
          } catch (IOException e) {
              e.printStackTrace();
              return false;
          }
          System.out.println(outputbuilder.toString());
          return outputbuilder.toString().contains("Administrator");
      }
      

      【讨论】:

        猜你喜欢
        • 2014-12-27
        • 2017-09-15
        • 2015-02-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-01-15
        • 1970-01-01
        • 2011-09-24
        相关资源
        最近更新 更多