检测Java应用程序是否作为Windows管理员运行

检测Java应用程序是否作为Windows管理员运行,java,windows,admin,privileges,Java,Windows,Admin,Privileges,我有一个Java应用程序。无论如何,我可以判断进程是否在Windows 7上以管理员权限运行。Java运行时环境中没有这样的功能,但可能在依赖于平台的本机例程中。请注意,通常最好的确定方法是实际尝试,并查看是否失败。仅通过尝试需要此类访问的操作(如绑定低编号端口或打开已知受保护的文件)。或者您可以执行以下操作: System.getenv().get(“用户”) 并查看是哪个用户启动了该过程 当我以我的身份运行它时,我得到了“goran”,当我与sudo一起运行它时,我得到了“root”。在Li

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

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

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

或者您可以执行以下操作:

System.getenv().get(“用户”)

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

当我以我的身份运行它时,我得到了“goran”,当我与sudo一起运行它时,我得到了“root”。在Linux上工作。
可能是需要的。

我在网上找到了这段代码片段,我想它可以帮你完成这项工作

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


关于它是如何工作的更多细节。

在我不得不在Linux机器上用Jenkins构建代码之前,答案中标记为best的方法对我来说非常有效。com.sun.security.auth.module.NTSystem()在那里不可用,使用sun软件包通常被认为是一种不好的做法:

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

正如所建议的,您可能希望抑制由此方法引起的错误消息。您可以通过设置
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);
            }
        }
    }
}

这里有一个在Windows10上的解决方案,我想它也可以在其他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;
    }
}

以下代码适合我

命令提示符命令

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


我在Linux中测试了我的答案。它可能不依赖操作系统,但我说不出来。嗯,这很有趣,让我试试这个,看看它在windows上做了什么。如果上面写着“管理员”,这就行了。请把结果贴出来。我真的很想知道这是否是Windows7上的独立操作系统,如果我运行这段代码,我会得到一个空值。但是,如果我运行System.getProperty(“user.name”),我会得到我的用户名。但是,这仍然不能说明我是否是管理员。尝试获取所有属性:
System.out.println(System.getenv())可能还有其他原因。请尝试:
System.out.println(System.getProperties())好ol'S-1-5-32-544。我应该想到的。。。。由于私有类的原因,仅适用于Sun JVM。请注意,此代码段测试活动用户是否是管理员,而不是用户是否已将应用程序作为提升进程启动!如果应用程序在管理员帐户上以正常权限运行,则此操作不起作用。仍然返回true…此代码可能仅适用于Oracle JRE,并且不保证适用于JRE的任何更新:从windows计算机获取“rt.jar”。将其添加到Linux机器上的类路径。然后在你的应用程序中有代码,可以查看它是否是windows PC,执行接受的答案,如果是Linux,则运行此问题的Linux答案。想到的第一个解决方案。对我来说,我只需要在Windows上做这个,所以我没有这个问题。这是Java做得有点差劲的事情之一。只是一个旁注,你应该把它作为一个注释添加进来。谢谢你关于rt.jar的提示!我要试一试。PS:我知道,这应该是一个评论,但不幸的是,由于stackoverflow授予权限的方式有些奇怪,以我目前的声誉,我只能对我自己的答案/问题发表评论=)谢谢。这对我很管用。我试图在程序文件中创建一个测试文件,并捕获IOException(访问被拒绝)。。。新文件(System.getenv(“programfiles”)+“/test.tst”).createNewFile()很好,但我建议您将状态缓存到私有静态变量中。它不会在程序的一个实例内改变。还有一件事-该函数不断产生输出,例如
Kvě072015149:14odp。java.util.prefs.WindowsPreferences警告:无法在根0x8000002处打开/创建prefs根节点Software\JavaSoft\prefs。Windows RegCreateKeyEx(…)返回了错误代码5。
有可能超出这些吗?@TomášZato我改进了我的答案注意,答案中的第二个代码块抛出了一个
NullPointerException
,原因是
System.setErr(null)
。要解决这个问题,请改用一个伪输出流:
System.setErr(newprintstream(newoutputstream(){@Override public void write(inti)抛出IOException{}}))
如果其他线程也不同步到
System.err,则行
synchronized(systemErr)
无效。