Holen Sie sich den Login-Benutzernamen in Java


90

Wie kann ich den Benutzernamen / Anmeldenamen in Java erhalten?

Dies ist der Code, den ich versucht habe ...

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

Ich bekomme eine, SecurityExceptionwenn ich versuche, diesen Code auszuführen. Könnte mir bitte jemand sagen, ob ich in die richtige Richtung gehe und mir helfen, das Problem zu verstehen.


3
Ich habe Angst, Sie falsch zu verstehen, aber ich verstehe Ihre Frage nicht. Welcher Login-Benutzername? Windows / GNU Linux Login? Grundlegende Authentifizierung auf einem Webserver?
Guerda

Es ist unmöglich, etwas zu verstehen, wenn keine Details veröffentlicht werden
matt b

Tut mir leid, Leute. Ich bin neu in Java und es ist jetzt ein bisschen schwierig, einen Sinn zu ergeben.
George Profenza

Antworten:


221
System.getProperty("user.name")

4
+1 Sie können die System.properties drucken, um viele Informationen zu erhalten, mit denen die VM initialisiert wird
Markus Lausberg

3
Für mich gibt dies den Namen des Benutzers aus, der die VM ausführt. Nicht der angemeldete Benutzer in der Java-Anwendung.
Tom Brito

1
Ist dies irgendwo in einer weit verbreiteten Bibliothek von Drittanbietern definiert? Oder ist irgendwo in JDK eine Konstante definiert, die Klassen für den user.nameEigenschaftsnamen bereitstellt?
Jeff Evans

29

unter Unix:

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

in Windows:

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

in Solaris:

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

49
Dieser Code widerspricht Javas Philosophie, einmal zu schreiben, überall auszuführen (Einführung von betriebssystemspezifischem Code) und zweitens eine Abhängigkeit von der Java-Implementierung von Sun zu schaffen.
Jin Kim

14
Der Versuch, den Benutzernamen zu erhalten, ist per Definition plattformspezifisch. Eine JVM, die auf einem Einzelbenutzersystem ausgeführt wird, hat möglicherweise überhaupt keinen Benutzernamen.
Chinmay Kanchi

8
@ChinmayKanchi: Wenn es keinen Benutzernamen gibt, sollte die user.nameEigenschaft einfach null sein. Ich stimme @JinKim zu, schreibe keine OS-abhängigen Sachen.
LS

2
user.name kann in der Befehlszeile festgelegt werden, daher hängt es sehr stark vom Anwendungsfall ab
Alice Purcell

3
Klassen unter com.sun-Paketen sollten nicht von einem Entwickler verwendet werden. Sie sind intern und können sich in Zukunft ändern.
CHiRo79

17

Inspiriert von der Antwort von @newacct , einem Code, der auf jeder Plattform kompiliert werden kann:

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

Gute Verwendung der Reflexion :)
Zizouz212

5
Dies wird unter Windows unterbrochen, da die Methode zum Abrufen des Benutzernamens auf NTSystem "getName ()" und nicht "getUsername ()" lautet. Ich nehme an, Sie können eine weitere Überprüfung durchführen und dann die richtige Methode aufrufen. Seltsamerweise wird dies von der JRE nicht in einen OS-agnostischen Mechanismus abstrahiert?
John Mark Scarborough

1
Auf die com.sunKlassen kann in Java 9+ standardmäßig nicht zugegriffen werden. Diese Lösung funktioniert nicht.
Thunderforge

Wenn keine neue API hinzugefügt wurde, ist das einzige, was in Java 9 funktionieren wird, die Lösung von dfa .
Thunderforge

15

System.getProperty ("user.name") ist keine gute Sicherheitsoption, da diese Umgebungsvariable gefälscht werden könnte: C: \ set USERNAME = "Joe Doe" java ... // gibt Ihnen System.getProperty ("user". Name ") Du solltest tun:

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

JDK 1.5 und höher.

Ich benutze es in einem Applet und es muss signiert werden. Infoquelle


4
Dies ist keine vollständige Lösung, da sie nur unter Windows funktioniert.
LS

1
Könnte dies auch gefälscht werden, z. B. mit einem benutzerdefinierten Klassenladeprogramm oder einer benutzerdefinierten Implementierung von com.sun.security.auth.module.NYSystemhöher im Klassenpfad? Ich weiß nicht, ob die Java-Laufzeit versucht, solche Exploits zu verhindern, aber ich denke nicht, dass es eine unumstößliche Möglichkeit gibt, sie "sicher" zu machen, außer indem Code auf einer Box ausgeführt wird, auf die der potenziell böswillige Client nicht zugreifen kann .
Bacar

4
Ich habe es gerade erfolgreich geschafft, die Implementierung von NTSystem.getName () mithilfe von PowerMock zu ersetzen (von dem ich glaube, dass es einen benutzerdefinierten Klassenladeprogramm verwendet), sodass Sie sich aus Sicherheitsgründen wirklich nicht auf so etwas verlassen können ... aber ich weiß es nicht wie die Dinge in der Applet-Welt sind. Ich hätte gedacht, wenn jemand benutzerdefinierte Systemeigenschaften bereitstellen kann, kann er auch benutzerdefinierte Klassen oder benutzerdefinierte Klassenladeprogramme bereitstellen.
Bacar

1
-1 Weil es nur unter Windows funktioniert. Sie sollten dies NICHT verwenden.
Stommestack

@bacar: Ich stimme zu, dass man sich nicht darauf verlassen sollte und denke, dass man ziemlich sicher ist. Aber meiner Meinung nach geht es bei Sicherheit um "Ebenen". Und es ist viel einfacher, die Umgebungsvariable zu ändern, als eine Methode per Powermock zu testen. In einem Nicht-IT-Unternehmen, das NTSystem anstelle der Umgebungsvariablen verwendet, halbiert sich die Anzahl der Personen, die es schaffen, mehr als die Hälfte: P. Sie erhalten also ein bisschen mehr Sicherheit, verlieren aber auf der Straße einige Java-Konventionen.
Calon

6

Mit JNA ist es einfach:

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
Dies funktioniert nicht, wenn Sie als Domänenbenutzer angemeldet sind, aber es gibt auch einen lokalen Benutzer mit demselben Namen. getAccountByName gibt Informationen für den lokalen Benutzer zurück.
Dave

2

Das 'set Username = "Username"' ist eine temporäre Überschreibung, die nur existiert, solange das cmd-Fenster noch aktiv ist. Sobald es beendet wird, verliert die Variable an Wert. Also ich denke das

System.getProperty ("user.name");

ist immer noch ein kurzer und präziser Code.


1

System.getenv().get("USERNAME"); - funktioniert unter Windows!

In den Umgebungseigenschaften haben Sie die Informationen, die Sie über Computer und Host benötigen! Ich sage es noch einmal! Funktioniert auf WINDOWS!


Was ist mit System.getenv("username")? :)
ROMANIA_engineer

Wenn die VM - beispielsweise Tomcat - als Windows-Dienst gestartet wird, gibt sie etwas zurück, das den Hostnamen enthält
Deepak

0

Unten finden Sie eine Lösung NUR für WINDOWS

In Fällen, in denen die Anwendung (wie Tomcat) als Windows-Dienst gestartet wird, geben System.getProperty ("user.name") oder System.getenv (). Get ("USERNAME") den Benutzer zurück, der den Dienst gestartet hat, und nicht den aktuell angemeldeter Benutzername.

Auch in Java 9 ist der Zugriff auf die Klassen NTSystem usw. nicht möglich

Problemumgehung für Windows: Sie können wmic verwenden , daher müssen Sie den folgenden Befehl ausführen

wmic ComputerSystem get UserName

Wenn verfügbar, wird die Ausgabe des Formulars zurückgegeben:

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

Hinweis: Für Windows müssen Sie cmd / c als Präfix verwenden. Im Folgenden finden Sie ein grobes Programm als Beispiel:

    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());
    }
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.