Определить, запускалось ли приложение Java от имени администратора Windows

У меня есть Java-приложение. В любом случае я могу сказать, был ли процесс запущен с правами администратора в Windows 7.


person user489041    schedule 03.12.2010    source источник
comment
Я проверил свой ответ в Linux. Вероятно, это не зависит от ОС, но я не могу сказать.   -  person Goran Jovic    schedule 04.12.2010


Ответы (8)


Я нашел этот фрагмент кода в Интернете, который, я думаю, сделает эту работу за вас.

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.

Вот ссылка для получения более подробной информации о том, как это работает.

person Codemwnci    schedule 03.12.2010
comment
Старый добрый S-1-5-32-544. Я должен был подумать об этом. - person Tom; 04.12.2010
comment
... И только с Sun JVM из-за частных занятий. - person Thorbjørn Ravn Andersen; 04.12.2010
comment
Обратите внимание, что этот фрагмент проверяет, является ли активный пользователь администратором, а не запустил ли пользователь приложение как процесс с повышенными правами! - person tbacker; 05.09.2013
comment
Это не работает, если приложение запущено с обычными правами в учетной записи администратора. Все равно возвращает истину... - person BullyWiiPlaza; 25.08.2015
comment
Этот код, скорее всего, будет работать только с Oracle JRE и не гарантирует работу с любым обновлением JRE: oracle.com/technetwork/java/faq-sun-packages-142232.html - person Novaterata; 21.04.2017

Я нашел другое решение, которое кажется независимым от платформы. Он пытается записать системные настройки. Если это не удается, пользователь может не быть администратором.

Как предложил 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);
            }
        }
    }
}
person MyPasswordIsLasercats    schedule 08.05.2014
comment
Хорошо, но я предлагаю кэшировать статус в закрытую статическую переменную. Это не изменится в пределах одного экземпляра программы. - person Tomáš Zato - Reinstate Monica; 07.05.2015
comment
@TomášZato Вы определенно правы в том, что это не изменится, но я хотел сделать пример кода как можно короче. - person MyPasswordIsLasercats; 07.05.2015
comment
Еще одна вещь - функция продолжает выдавать вывод, например 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. Можно ли их подавить? - person Tomáš Zato - Reinstate Monica; 07.05.2015
comment
@TomášZato Я улучшил свой ответ - person MyPasswordIsLasercats; 08.05.2015
comment
Большое спасибо! :) К сожалению, я не могу проголосовать за вас во второй раз. Надеюсь, кто-то еще будет. - person Tomáš Zato - Reinstate Monica; 08.05.2015
comment
Это верное решение, которое работает. Подавление важно. +1 - person BullyWiiPlaza; 25.08.2015
comment
Обратите внимание, что второй блок кода в ответе выдает NullPointerException из-за System.setErr(null). Чтобы исправить это, используйте вместо этого фиктивный поток вывода: System.setErr(new PrintStream(new OutputStream() { @Override public void write(int i) throws IOException { } })); - person MC Emperor; 15.09.2015
comment
Строка synchronized(systemErr) не действует, если другие потоки также не синхронизируются с System.err. - person Beto Neto; 19.09.2017
comment
+1, потому что это обнаруживает (я думаю, это называется) административный контекст, а не только пользователей-администраторов. Я являюсь администратором на своем ПК, но большую часть времени я не запускаю программы с правами администратора. Чтобы вышеуказанное вернуло true, я должен выполнить свою программу, используя Run as Administrator, что отличается от простого запуска программы от имени пользователя, входящего в группу администраторов. - person Jonathan; 03.11.2017

В Java Runtime Environment нет такой возможности, но она может быть в собственной подпрограмме, зависящей от платформы. Обратите внимание, что обычно лучший способ убедиться в этом — это попытаться сделать это на самом деле и посмотреть, не получится ли.

person Thorbjørn Ravn Andersen    schedule 03.12.2010

Только при попытке выполнить операцию, требующую такого доступа (например, привязать порт с низким номером или открыть заведомо защищенный файл).

person bmargulies    schedule 03.12.2010
comment
Спасибо. Это сработало для меня. Я попытался создать тестовый файл в программных файлах и поймал IOException (доступ запрещен)... новый файл (System.getenv (programfiles)+/test.tst).createNewFile() - person Brian O Carroll; 14.04.2014

Метод из ответа, отмеченного как лучший, отлично работал для меня до того момента, когда мне пришлось создавать код в Jenkins на машине с Linux. com.sun.security.auth.module.NTSystem() там недоступен, и использование пакетов sun обычно считается плохой практикой: ссылка

person Alex Fedulov    schedule 07.03.2012
comment
Возьмите «rt.jar» с вашего компьютера с Windows. Добавьте его в путь к классам на вашем компьютере с Linux. Затем у вас есть код внутри вашего приложения, который может увидеть, является ли это ПК с Windows, выполнить принятый ответ, если это Linux, запустить ответы Linux из этого вопроса. Первое решение, которое приходит на ум. Для меня мне просто нужно было сделать это в Windows, поэтому у меня не было этой проблемы. Это одна из тех вещей, с которыми Java не справляется. Просто примечание, вы должны добавить это как комментарий. - person user489041; 07.03.2012
comment
Спасибо за подсказку относительно rt.jar! Я дам ему попробовать. PS: я знаю, что это должен был быть комментарий, но, к сожалению, из-за несколько странного способа, которым stackoverflow дает разрешения, с моей текущей репутацией мне разрешено комментировать только мои собственные ответы/вопросы =) - person Alex Fedulov; 07.03.2012

Или вы можете сделать это:

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

И посмотреть, какой пользователь запустил процесс.

Когда я запускаю его как я, я получаю «goran», когда я запускаю его с помощью sudo, я получаю «root». Работает на Линукс. Наверное то, что нужно.

person Goran Jovic    schedule 03.12.2010
comment
Хм, это интересно, позвольте мне попробовать и посмотреть, что это делает на Windows. Если он говорит admin, это будет работать. - person user489041; 04.12.2010
comment
И, пожалуйста, отпишитесь о результатах. Я действительно хотел бы знать, не зависит ли это от ОС - person Goran Jovic; 04.12.2010
comment
В Windows 7 я получаю нулевое значение, если запускаю этот код. Однако, если я запускаю System.getProperty(user.name), я получаю свое имя пользователя. Но это все еще не говорит, являюсь ли я администратором или нет. - person Codemwnci; 04.12.2010
comment
Интересно. Попробуйте получить все свойства: System.out.println(System.getenv()); Возможно, есть что-то еще. - person Goran Jovic; 04.12.2010
comment
Также попробуйте: System.out.println(System.getProperties()); - person Goran Jovic; 04.12.2010
comment
Хорошо, основываясь на том, что вы и Codemwnci сказали, это, очевидно, работает совсем по-другому в Windows, поэтому вам придется попробовать и посмотреть, что предложили другие. - person Goran Jovic; 04.12.2010
comment
При использовании getenv() ключом является USERNAME, поэтому ваш код будет System.getenv().get(USERNAME), результат будет таким же, как System.getProperty(user.name) - person Codemwnci; 04.12.2010
comment
Ну, мой getenv содержит оба ключа. До сих пор я даже не замечал USERNAME - person Goran Jovic; 04.12.2010

Вот решение для 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;
    }
}
person OnSN    schedule 24.08.2018

Приведенный ниже код сработал для меня

Команда командной строки

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");
}
person Vinayagam.D    schedule 14.02.2019