Uzyskaj nazwę użytkownika logowania w java


92

Jak mogę uzyskać nazwę użytkownika / nazwę logowania w Javie?

To jest kod, który wypróbowałem ...

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

Otrzymuję, SecurityExceptiongdy próbuję uruchomić ten kod. Czy ktoś mógłby mi powiedzieć, czy zmierzam we właściwym kierunku i pomóc mi zrozumieć problem.


3
Boję się źle cię zrozumieć, ale nie rozumiem twojego pytania. Która nazwa użytkownika do logowania? Logowanie do systemu Windows / GNU Linux? Podstawowe uwierzytelnianie na serwerze internetowym?
guerda

Nic nie można zrozumieć, gdy nie podano żadnych szczegółów
matt b

Przepraszam chłopaki. Jestem nowy w Javie i teraz jest to trochę trudne do zrozumienia.
George Profenza

Odpowiedzi:


225
System.getProperty("user.name")

4
+1 możesz wydrukować System.properties, aby uzyskać wiele informacji, z którymi maszyna wirtualna jest inicjalizowana
Markus Lausberg

3
Dla mnie to wyświetla nazwę użytkownika wykonującego maszynę wirtualną. Nie zalogowany użytkownik w aplikacji Java.
Tom Brito

1
Czy jest to zdefiniowane gdziekolwiek w ogólnodostępnej bibliotece innej firmy? A może gdziekolwiek w klasach dostarczonych przez JDK jest zdefiniowana stała dla user.namenazwy właściwości?
Jeff Evans

29

w systemie Unix:

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

w systemie Windows:

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

w Solarisie:

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

49
Ten kod jest sprzeczny z filozofią Javy polegającą na jednokrotnym pisaniu, uruchamianiu w dowolnym miejscu (wprowadzenie kodu specyficznego dla systemu operacyjnego), a po drugie, tworzy zależność od implementacji Javy firmy Sun.
Jin Kim

14
Próba uzyskania nazwy użytkownika jest z definicji specyficzna dla platformy. Maszyna JVM działająca w systemie jednego użytkownika może w ogóle nie mieć nazwy użytkownika.
Chinmay Kanchi

8
@ChinmayKanchi: Jeśli nie ma nazwy użytkownika, user.namewłaściwość powinna mieć wartość NULL. Zgadzam się z @JinKim, nie piszę rzeczy zależnych od systemu operacyjnego.
Mr. Lance E Sloan

2
user.name można ustawić w linii poleceń, tak że bardzo wiele zależy od tego, co jest use-case
Alicja Purcell

3
Klasy w pakietach com.sun nie powinny być używane przez programistów. Są wewnętrzne i mogą ulec zmianie w przyszłości.
CHiRo79,

17

zainspirowany odpowiedzią @newacct , kod, który można skompilować na dowolnej platformie:

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

Dobre wykorzystanie refleksji :)
Zizouz212

5
To się zepsuje w Windows, ponieważ metoda w NTSystem do pobrania nazwy użytkownika to „getName ()” a nie „getUsername ()”. Przypuszczam, że możesz przeprowadzić dalsze sprawdzenie, a następnie wywołać odpowiednią metodę. Dziwne, ale to nie jest wyabstrahowane przez JRE do mechanizmu agnostycznego systemu operacyjnego?
John Mark Scarborough

1
Na com.sunzajęcia nie są dostępne domyślnie w Java 9+. To rozwiązanie się nie sprawdzi.
Thunderforge,

Jeśli nie dodano nowego API, myślę, że jedyną rzeczą, która będzie działać w Javie 9, będzie rozwiązanie dfa .
Thunderforge

15

System.getProperty ("nazwa.użytkownika") nie jest dobrą opcją bezpieczeństwa, ponieważ ta zmienna środowiskowa może zostać sfałszowana: C: \ set USERNAME = "Joe Doe" java ... // da ci System.getProperty ("user. name ”) Powinieneś zrobić:

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

JDK 1.5 i nowsze.

Używam go w aplecie i musi być podpisany. źródło informacji


4
To nie jest kompletne rozwiązanie, ponieważ działa tylko pod Windows.
Mr. Lance E Sloan

1
Czy można to również sfałszować, np. Za pomocą niestandardowego com.sun.security.auth.module.NYSystemmodułu ładującego klasy lub niestandardowej implementacji wyższego w ścieżce klas? Nie wiem, czy środowisko wykonawcze Javy próbuje zapobiegać takim exploitom, ale nie sądzę, że będzie jakikolwiek niezawodny sposób, aby uczynić go `` bezpiecznym '', z wyjątkiem uruchomienia kodu na skrzynce niedostępnej dla potencjalnie złośliwego klienta .
Bacar

4
Właśnie udało mi się z powodzeniem zastąpić implementację NTSystem.getName () przy użyciu PowerMock (który, jak sądzę, używa niestandardowego modułu ładującego klasy), więc naprawdę nie można polegać na czymś takim w zakresie `` bezpieczeństwa '' ... jednak nie wiem jak sprawy mają się w świecie apletów. Pomyślałbym, że jeśli ktoś może zapewnić niestandardowe właściwości systemu, może również zapewnić niestandardowe klasy lub niestandardowe programy ładujące.
Bacar

1
-1 Ponieważ działa tylko w systemie Windows. NIE powinieneś tego używać.
stommestack

@bacar: Zgadzam się, że nie należy na tym polegać i uważać, że jest to całkiem bezpieczne. Ale moim zdaniem bezpieczeństwo to „poziomy”. O wiele łatwiej jest zmienić zmienną środowiskową niż powermocking metody. W firmie spoza IT używającej NTSystem zamiast zmiennej środowiskowej więcej niż o połowę zmniejsza liczbę osób, które są w stanie to zrobić: P. Zyskujesz więc trochę więcej bezpieczeństwa, ale z kolei tracisz niektóre konwencje Java w podróży.
Calon

6

Korzystanie z JNA jest proste:

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
To nie działa, jeśli jesteś zalogowany jako użytkownik domeny, ale istnieje również użytkownik lokalny o tej samej nazwie. getAccountByName zwróci informacje dla użytkownika lokalnego.
Dave,

2

„Set Nazwa =«Nazwa użytkownika»” jest tymczasowy przesłanianie że istnieje tylko tak długo, jak CMD okien jest wciąż w górę, raz jest zabijane, zmienna traci wartość. Więc myślę, że

System.getProperty ("nazwa.użytkownika");

to wciąż krótki i precyzyjny kod do użycia.


1

System.getenv().get("USERNAME"); - działa na oknach!

We właściwościach środowiska masz potrzebne informacje o komputerze i hoście! Powtarzam! Działa na WINDOWS!


O co chodzi System.getenv("username")? :)
ROMANIA_engineer

Praca Doensa, jeśli maszyna wirtualna - powiedzmy tomcat - zostanie uruchomiona jako usługa systemu Windows, zwraca coś, co zawiera nazwę hosta
Deepak,

0

Poniżej znajduje się rozwiązanie TYLKO dla WINDOWS

W przypadkach, gdy aplikacja (taka jak Tomcat) jest uruchamiana jako usługa systemu Windows, System.getProperty („nazwa.użytkownika”) lub System.getenv (). Get („NAZWA UŻYTKOWNIKA”) zwraca użytkownika, który uruchomił usługę, a nie nazwa aktualnie zalogowanego użytkownika.

Również w Javie 9 klasy NTSystem etc nie będą dostępne

Więc obejście dla Windows: możesz użyć wmic , więc musisz uruchomić poniższe polecenie

wmic ComputerSystem get UserName

Jeśli jest dostępny, zwróci dane wyjściowe w postaci:

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

Uwaga: W przypadku Windows musisz użyć cmd / c jako przedrostka, więc poniżej znajduje się prymitywny program jako przykład:

    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());
    }
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.