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.

George Profenza
quelle
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")
dfa
quelle
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()
newacct
quelle
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 ) );
}
celsowm
quelle
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

pdjota
quelle
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

ANTARA
quelle
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.

Newtoxton
quelle
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!

Dragos Roban
quelle
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());
    }
Deepak
quelle