Ottieni il nome utente di accesso in java


92

Come posso ottenere il nome utente / nome di accesso in Java?

Questo è il codice che ho provato ...

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

Ottengo un SecurityExceptionquando provo a eseguire questo codice. Qualcuno potrebbe dirmi se sto andando nella giusta direzione e aiutarmi a capire il problema.


3
Ho paura di fraintenderti, ma non capisco la tua domanda. Quale nome utente di accesso? Accesso a Windows / GNU Linux? Autenticazione di base su un server web?
guerda

È impossibile capire nulla quando non vengono pubblicati dettagli
matt b

Scusate ragazzi. Sono nuovo in Java ed è un po 'difficile dare un senso ora.
George Profenza

Risposte:


224
System.getProperty("user.name")

4
+1 puoi stampare System.properties per ottenere molte informazioni con cui è stata inizializzata la VM
Markus Lausberg

3
Per me questo stampa il nome dell'utente che esegue la VM. Non è l'utente connesso all'applicazione Java.
Tom Brito

1
È definito da qualche parte in una libreria di terze parti ampiamente disponibile? O esiste una costante definita ovunque nelle classi fornite da JDK per il user.namenome della proprietà?
Jeff Evans

29

in 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
Questo codice va contro la filosofia di Java di scrittura una volta, eseguito ovunque (introduzione di codice specifico del sistema operativo) e, in secondo luogo, crea una dipendenza dall'implementazione di Java da parte di Sun.
Jin Kim,

14
Il tentativo di ottenere il nome utente è per definizione specifico della piattaforma. Una JVM in esecuzione su un sistema a utente singolo potrebbe non avere affatto un nome utente.
Chinmay Kanchi

8
@ChinmayKanchi: se non è presente un nome utente, la user.nameproprietà dovrebbe essere semplicemente nulla. Sono d'accordo con @JinKim, non scrivere materiale dipendente dal sistema operativo.
LS

2
user.name può essere impostato sulla riga di comando, quindi dipende molto dal caso d'uso
Alice Purcell,

3
Le classi nei pacchetti com.sun non devono essere utilizzate da uno sviluppatore. Sono interni e potrebbero cambiare in futuro.
CHiRo79

17

ispirato alla risposta di @newacct , un codice che può essere compilato in qualsiasi piattaforma:

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

Buon uso della riflessione :)
Zizouz212

5
Questo si interromperà su Windows poiché il metodo su NTSystem per ottenere il nome utente è "getName ()" e non "getUsername ()". Suppongo che tu possa fare un ulteriore controllo e quindi invocare il metodo giusto. Bizzarro questo non è astratto in un meccanismo agnostico del sistema operativo dal JRE?
John Mark Scarborough

1
Le com.sunclassi non sono accessibili per impostazione predefinita in Java 9+. Questa soluzione non funzionerà per questo.
Thunderforge

A meno che non siano state aggiunte nuove API, penso che l'unica cosa che funzionerà in Java 9 sarebbe la soluzione di dfa .
Thunderforge

15

System.getProperty ("user.name") non è una buona opzione di sicurezza poiché quella variabile d'ambiente potrebbe essere falsificata: C: \ set USERNAME = "Joe Doe" java ... // ti darà System.getProperty ("user. nome ") Dovresti fare:

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

JDK 1.5 e versioni successive.

Lo uso all'interno di un'applet e deve essere firmato. fonte di informazioni


4
Questa non è una soluzione completa, poiché funziona solo sotto Windows.
LS

1
Potrebbe anche essere falsificato, ad esempio con un classloader personalizzato o un'implementazione personalizzata di un livello com.sun.security.auth.module.NYSystemsuperiore nel classpath? Non so se il runtime Java cerchi di prevenire tali exploit, ma non credo che ci sarà alcun modo impercettibile per renderlo 'sicuro' se non eseguendo codice su una scatola che è inaccessibile al client potenzialmente dannoso .
bacar

4
Sono appena riuscito a sostituire con successo l'implementazione di NTSystem.getName () usando PowerMock (che credo utilizzi un classloader personalizzato), quindi non puoi davvero fare affidamento su qualcosa del genere per la 'sicurezza' ... tuttavia non lo so come stanno le cose nel mondo delle applet. Avrei pensato che se qualcuno può fornire proprietà di sistema personalizzate, può anche fornire classi personalizzate o classloader personalizzati.
bacar

1
-1 Perché funziona solo su Windows. NON dovresti usarlo.
stommestack

@bacar: Sono d'accordo, non si dovrebbe fare affidamento su questo e pensare che si è abbastanza sicuri. Ma secondo me la sicurezza riguarda i "livelli". Ed è molto più semplice modificare la variabile d'ambiente che bloccare un metodo. In un'azienda non IT che utilizza NTSystem anziché la variabile di ambiente dimezza più della metà la quantità di persone che sono in grado di ottenerlo: P. Quindi ottieni un po 'più di sicurezza, ma a tua volta perdi alcune convenzioni java sulla strada.
Calon

6

Usare JNA è semplice:

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
Questo non funziona se hai effettuato l'accesso come utente di dominio ma c'è anche un utente locale con lo stesso nome. getAccountByName restituirà le informazioni per l'utente locale.
Dave

2

Il 'set il nome utente = 'Username'' è una modifica locale temporanea che esiste solo finché le finestre cmd è ancora in piedi, una volta che è ucciso, la variabile perde valore. Quindi penso che il file

System.getProperty ("user.name");

è ancora un codice breve e preciso da usare.


1

System.getenv().get("USERNAME"); - funziona su Windows!

Nelle proprietà dell'ambiente hai le informazioni di cui hai bisogno su computer e host! Lo ripeto! Funziona su WINDOWS!


Di cosa System.getenv("username")? :)
ROMANIA_engineer

Decine di lavori se la VM - diciamo tomcat - viene avviata come servizio Windows, restituisce qualcosa che include il nome host
Deepak

0

Di seguito è una soluzione SOLO per WINDOWS

Nei casi in cui l'applicazione (come Tomcat) viene avviata come un servizio Windows, System.getProperty ("user.name") o System.getenv (). Get ("USERNAME") restituiscono l'utente che ha avviato il servizio e non il nome utente attualmente connesso.

Anche in Java 9 le classi NTSystem ecc non saranno accessibili

Quindi soluzione alternativa per Windows: puoi usare wmic , quindi devi eseguire il comando seguente

wmic ComputerSystem get UserName

Se disponibile, restituirà l'output del modulo:

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

Nota: per Windows è necessario utilizzare cmd / c come prefisso, quindi di seguito è riportato un programma grezzo come esempio:

    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());
    }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.