Отримати ім’я користувача для входу в Java


92

Як я можу отримати ім'я користувача / ім'я для входу в Java?

Це код, який я спробував ...

try{
    LoginContext lc = new LoginContext(appName,new TextCallbackHandler());
    lc.login();
    Subject subject = lc.getSubject();
    Principal principals[] = (Principal[])subject.getPrincipals().toArray(new Principal[0]);

    for (int i=0; i<principals.length; i++) {
        if (principals[i] instanceof NTUserPrincipal || principals[i] instanceof UnixPrincipal) {
            String loggedInUserName = principals[i].getName();
        }
    }

}
catch(SecurityException se){
    System.out.println("SecurityException: " + se.getMessage());
}

Я отримую, SecurityExceptionколи намагаюся запустити цей код. Хтось може сказати мені, чи рухаюсь я в правильному напрямку, і допомогти мені зрозуміти проблему.


3
Я боюся вас неправильно зрозуміти, але я не розумію вашого запитання. Яке ім’я користувача для входу? Логін для Windows / GNU Linux? Базова автентифікація на веб-сервері?
guerda

Неможливо нічого зрозуміти, коли жодна інформація не розміщена
matt b,

Вибачте хлопці. Я новачок у Java, і зараз трохи важко осмислити.
Джордж Профенца

Відповіді:


224
System.getProperty("user.name")

4
+1 ви можете надрукувати System.properties, щоб отримати багато інформації, за допомогою якої ініціалізується ВМ
Маркус Лаусберг,

3
Для мене це друкує ім'я користувача, який виконує ВМ. Не зареєстрований користувач у програмі java.
Том Бріто

1
Це визначено де-небудь у широко доступній сторонній бібліотеці? Або є де-небудь визначена константа в наданих JDK класах для назви user.nameвластивості?
Джефф Еванс,

29

в Unix:

new com.sun.security.auth.module.UnixSystem().getUsername()

у Windows:

new com.sun.security.auth.module.NTSystem().getName()

в Соляріс:

new com.sun.security.auth.module.SolarisSystem().getUsername()

49
Цей код суперечить філософії Java - писати один раз, запускати будь-де (введення коду, який відповідає ОС), а по-друге, створює залежність від реалізації Java Java від Sun.
Джин Кім

14
Спроба отримати ім’я користувача за визначенням залежить від платформи. JVM, що працює в однокористувацькій системі, може взагалі не мати імені користувача.
Чінмай Канчі

8
@ChinmayKanchi: Якщо немає імені користувача, тоді user.nameвластивість має бути просто нульовим. Я погоджуюсь з @JinKim, не пишіть матеріали, залежні від ОС.
LS

2
user.name можна встановити в командному рядку, тому це дуже залежить від того, яким є варіант використання
Alice Purcell

3
Класи під пакетами com.sun розробник не повинен використовувати. Вони є внутрішніми і можуть змінитися в майбутньому.
CHiRo79,

17

натхненний відповіддю @newacct , кодом, який можна скомпілювати на будь-якій платформі:

String osName = System.getProperty( "os.name" ).toLowerCase();
String className = null;
String methodName = "getUsername";

if( osName.contains( "windows" ) ){
    className = "com.sun.security.auth.module.NTSystem";
    methodName = "getName";
}
else if( osName.contains( "linux" ) ){
    className = "com.sun.security.auth.module.UnixSystem";
}
else if( osName.contains( "solaris" ) || osName.contains( "sunos" ) ){
    className = "com.sun.security.auth.module.SolarisSystem";
}

if( className != null ){
    Class<?> c = Class.forName( className );
    Method method = c.getDeclaredMethod( methodName );
    Object o = c.newInstance();
    System.out.println( method.invoke( o ) );
}

Хороше використання роздумів :)
Zizouz212

5
Це не працює в Windows, оскільки метод NTSystem для отримання імені користувача - "getName ()", а не "getUsername ()". Припускаю, ви можете зробити подальшу перевірку, а потім застосувати правильний метод. Химерно, проте JRE не абстрагує це механізм агностики ОС?
Джон Марк Скарборо,

1
Ці com.sunкласи не доступні за умовчанням в Java 9+. Це рішення для нього не спрацює.
Thunderforge

Якщо не буде додано якийсь новий API, я думаю, єдиним, що працюватиме в Java 9, буде рішення dfa .
Thunderforge

15

System.getProperty ("user.name") не є хорошим варіантом безпеки, оскільки цю змінну середовища можна сфальсифікувати: C: \ set USERNAME = "Joe Doe" java ... // надасть вам System.getProperty ("користувач. name ") Ви повинні зробити:

com.sun.security.auth.module.NTSystem NTSystem = new com.sun.security.auth.module.NTSystem();
System.out.println(NTSystem.getName());

JDK 1,5 і вище.

Я використовую його в аплеті, і він повинен бути підписаний. інформаційне джерело


4
Це не повне рішення, оскільки воно працює лише під Windows.
LS

1
Чи може це також бути підроблено, наприклад, за допомогою користувацького завантажувача класів або спеціальної реалізації com.sun.security.auth.module.NYSystemвищої версії у класі шляху? Я не знаю, чи намагається виконати Java запобігати подібним експлоїтам, але я не думаю, що буде якийсь непорушний спосіб зробити його "захищеним", за винятком запуску коду у вікні, недоступному для потенційно шкідливого клієнта .
bacar

4
Мені просто вдало замінити реалізацію NTSystem.getName () за допомогою PowerMock (який, на мою думку, використовує спеціальний завантажувач класів), тому ви дійсно не можете покладатися на щось подібне для `` безпеки '' ... однак я не знаю як справи в світі аплетів. Я міг би подумати, що якщо хтось може надати власні властивості системи, то він може також забезпечити власні класи або власні завантажувачі класів.
bacar

1
-1 Оскільки він працює лише у Windows. Вам НЕ слід користуватися цим.
stommestack

@bacar: Я згоден, що на це не слід покладатися і думати, що він досить безпечний. Але, на мій погляд, безпека - це "рівень". І це набагато легше змінити змінну середовища, ніж метод примусового знущання. У не-ІТ-компанії, яка використовує NTSystem, а не змінну середовища, більш ніж вдвічі зменшує кількість людей, які можуть її використати: P. Таким чином, ви отримуєте трохи більше безпеки, але в свою чергу втрачаєте деякі правила Java на дорозі.
Калон

6

Використовуючи JNA просто:

String username = Advapi32Util.getUserName();
System.out.println(username);

Advapi32Util.Account account = Advapi32Util.getAccountByName(username);
System.out.println(account.accountType);
System.out.println(account.domain);
System.out.println(account.fqn);
System.out.println(account.name);
System.out.println(account.sidString);

https://github.com/java-native-access/jna


1
Це не працює, якщо ви ввійшли як користувач домену, але є також локальний користувач з тим самим іменем. getAccountByName поверне інформацію для локального користувача.
Дейв

2

«Встановлено Ім'я користувача =" Ім'я користувача "» тимчасова корекція , яка існує тільки до тих пір , поки CMD вікна все ще вгору, як тільки він убитий, змінна втрачає значення. Тож я думаю

System.getProperty ("ім'я користувача");

все ще короткий і точний код для використання.


1

System.getenv().get("USERNAME"); - працює на вікнах!

У властивостях середовища у вас є необхідна інформація про комп’ютер та хост! Я ще раз кажу! Працює на WINDOWS!


Що про System.getenv("username")? :)
ROMANIA_engineer

Робота Doens, якщо віртуальна машина - скажімо tomcat - запускається як служба Windows, вона повертає те, що включає ім'я хоста
Deepak,

0

Нижче наведено рішення ТІЛЬКИ для WINDOWS

У випадках, коли додаток (як Tomcat) запускається як служба Windows, System.getProperty ("ім'я користувача") або System.getenv (). Get ("ІМЯ КОРИСТУВАЧА) повертає користувача, який запустив службу, а не поточне зареєстроване ім'я користувача.

Також у Java 9 класи NTSystem тощо не будуть доступні

Отже, обхідний шлях для Windows: Ви можете використовувати wmic , тому вам доведеться запустити наведену нижче команду

wmic ComputerSystem get UserName

Якщо доступно, це поверне вивід форми:

UserName
{domain}\{logged-in-user-name}

Примітка: Для Windows вам потрібно використовувати cmd / c як префікс, тому нижче наведено сиру програму як приклад:

    Process exec = Runtime.getRuntime().exec("cmd /c wmic ComputerSystem get UserName".split(" "));
    System.out.println(exec.waitFor());
    try (BufferedReader bw = new BufferedReader(new InputStreamReader(exec.getInputStream()))) {
        System.out.println(bw.readLine() + "\n" + bw.readLine()+ "\n" + bw.readLine());
    }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.