Obtenez le nom d'utilisateur de connexion en java


92

Comment puis-je obtenir le nom d'utilisateur / nom de connexion en Java?

C'est le code que j'ai essayé ...

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

J'obtiens un SecurityExceptionlorsque j'essaye d'exécuter ce code. Quelqu'un pourrait-il me dire si je vais dans la bonne direction et m'aider à comprendre le problème.


3
J'ai peur de mal vous comprendre, mais je ne comprends pas votre question. Quel identifiant de connexion? Connexion Windows / GNU Linux? Authentification de base sur un serveur Web?
guerda

Il est impossible de comprendre quoi que ce soit quand aucun détail n'est affiché
matt b

Désolé les gars. Je suis nouveau sur Java et c'est un peu difficile à comprendre maintenant.
George Profenza

Réponses:


224
System.getProperty("user.name")

4
+1 vous pouvez imprimer le System.properties pour obtenir beaucoup d'informations avec lesquelles la VM est initialisée
Markus Lausberg

3
Pour moi, cela imprime le nom de l'utilisateur exécutant la VM. Pas l'utilisateur connecté sur l'application java.
Tom Brito

1
Est-ce défini n'importe où dans une bibliothèque tierce largement disponible? Ou y a-t-il une constante définie n'importe où dans les classes fournies par JDK pour le user.namenom de la propriété?
Jeff Evans le

29

sous Unix:

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

sous Windows:

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

sous Solaris:

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

49
Ce code va à l'encontre de la philosophie de Java d'écrire une fois, de s'exécuter n'importe où (introduction de code spécifique au système d'exploitation), et d'autre part, il crée une dépendance à l'implémentation de Java par Sun.
Jin Kim

14
Essayer d'obtenir le nom d'utilisateur est par définition spécifique à la plate-forme. Une machine virtuelle Java exécutée sur un système mono-utilisateur peut ne pas avoir du tout de nom d'utilisateur.
Chinmay Kanchi

8
@ChinmayKanchi: S'il n'y a pas de nom d'utilisateur, la user.namepropriété doit simplement être nulle. Je suis d'accord avec @JinKim, n'écrivez pas de trucs dépendant du système d'exploitation.
LS

2
user.name peut être défini sur la ligne de commande, cela dépend donc beaucoup du cas d'utilisation
Alice Purcell

3
Les classes sous les packages com.sun ne doivent pas être utilisées par un développeur. Ils sont internes et peuvent changer à l'avenir.
CHiRo79

17

inspiré de la réponse de @newacct , un code qui peut être compilé dans n'importe quelle plateforme:

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

Bon usage de la réflexion :)
Zizouz212

5
Cela ne fonctionnera pas sous Windows car la méthode sur NTSystem pour obtenir le nom d'utilisateur est "getName ()" et non "getUsername ()". Je suppose que vous pouvez faire une vérification supplémentaire, puis invoquer la bonne méthode. Bizarre, cela n'est pas résumé dans un mécanisme indépendant du système d'exploitation par le JRE?
John Mark Scarborough

1
Les com.sunclasses ne sont pas accessibles par défaut dans Java 9+. Cette solution ne fonctionnera pas pour cela.
Thunderforge

À moins qu'une nouvelle API ne soit ajoutée, je pense que la seule chose qui fonctionnera dans Java 9 serait la solution de dfa .
Thunderforge

15

System.getProperty ("user.name") n'est pas une bonne option de sécurité car cette variable d'environnement pourrait être falsifiée: C: \ set USERNAME = "Joe Doe" java ... // vous donnera System.getProperty ("user. name ") Vous devez faire:

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

JDK 1.5 et supérieur.

Je l'utilise dans une applet, et il doit être signé. source d'informations


4
Ce n'est pas une solution complète, car cela ne fonctionne que sous Windows.
LS

1
Cela pourrait-il être également usurpé, par exemple avec un chargeur de classe personnalisé ou une implémentation personnalisée de com.sun.security.auth.module.NYSystemplus haut dans le chemin de classe? Je ne sais pas si le runtime Java essaie de se prémunir contre de tels exploits, mais je ne pense pas qu'il y ait un moyen infaillible de le rendre `` sécurisé '' sauf en exécutant du code sur une boîte inaccessible au client potentiellement malveillant .
bacar

4
J'ai juste réussi à remplacer l'implémentation de NTSystem.getName () en utilisant PowerMock (qui, je crois, utilise un chargeur de classe personnalisé), donc vous ne pouvez vraiment pas compter sur quelque chose comme ça pour la `` sécurité '' ... mais je ne sais pas comment les choses sont dans le monde des applets. J'aurais pensé que si quelqu'un pouvait fournir des propriétés système personnalisées, il pouvait également fournir des classes personnalisées ou des chargeurs de classes personnalisés.
bacar

1
-1 Parce que cela ne fonctionne que sous Windows. Vous ne devez PAS utiliser cela.
stommestack

@bacar: Je suis d'accord, qu'il ne faut pas se fier à cela et penser que l'on est assez sûr. Mais à mon avis, la sécurité concerne les «niveaux». Et il est beaucoup plus facile de modifier la variable d'environnement que de verrouiller une méthode. Dans une entreprise non informatique utilisant NTSystem plutôt que la variable d'environnement, réduit de plus de moitié le nombre de personnes capables de le réaliser: P. Ainsi, vous obtenez un peu plus de sécurité, mais vous perdez à votre tour certaines conventions Java sur la route.
Calon

6

Utiliser JNA c'est simple:

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
Cela ne fonctionne pas si vous êtes connecté en tant qu'utilisateur de domaine, mais qu'il existe également un utilisateur local du même nom. getAccountByName renverra des informations pour l'utilisateur local.
Dave

2

Le 'set Username = "Username"' est un remplacement temporaire qui n'existe que tant que la fenêtre cmd est toujours active, une fois qu'elle est tuée, la variable perd de sa valeur. Donc je pense que le

System.getProperty ("nom.utilisateur");

est toujours un code court et précis à utiliser.


1

System.getenv().get("USERNAME"); - fonctionne sur Windows!

Dans les propriétés de l'environnement, vous avez les informations dont vous avez besoin sur l'ordinateur et l'hôte! Je le répète! Fonctionne sur WINDOWS!


Et quoi System.getenv("username")? :)
ROMANIA_engineer

Donne du travail si la VM - disons tomcat - est démarrée en tant que service Windows, elle renvoie quelque chose qui inclut le nom d'hôte
Deepak

0

Voici une solution pour WINDOWS UNIQUEMENT

Dans les cas où l'application (comme Tomcat) est démarrée en tant que service Windows, System.getProperty ("user.name") ou System.getenv (). Get ("USERNAME") renvoie l'utilisateur qui a démarré le service et non le nom d'utilisateur actuellement connecté.

Aussi dans Java 9, les classes NTSystem etc. ne seront pas accessibles

Donc, solution de contournement pour Windows: vous pouvez utiliser wmic , vous devez donc exécuter la commande ci-dessous

wmic ComputerSystem get UserName

Si disponible, cela retournera la sortie du formulaire:

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

Remarque: pour Windows, vous devez utiliser cmd / c comme préfixe, voici donc un programme brut comme exemple:

    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());
    }
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.