Obter nome de usuário de login em java


92

Como posso obter o nome de usuário / nome de login em Java?

Este é o código que tentei ...

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

Recebo um SecurityExceptionquando tento executar este código. Alguém poderia me dizer se estou indo na direção certa e me ajudar a entender o problema.


3
Tenho medo de entendê-lo mal, mas não entendi sua pergunta. Qual nome de usuário de login? Login do Windows / GNU Linux? Autenticação básica em um servidor web?
guerda

É impossível entender qualquer coisa quando nenhum detalhe é postado
matt b

Desculpem rapazes. Sou novo em Java e é um pouco difícil fazer sentido agora.
George Profenza

Respostas:


224
System.getProperty("user.name")

4
+1 você pode imprimir o System.properties para obter muitas informações com as quais a VM é inicializada
Markus Lausberg

3
Para mim, isso imprime o nome do usuário executando a VM. Não é o usuário conectado no aplicativo java.
Tom Brito

1
Isso está definido em qualquer lugar em uma biblioteca de terceiros amplamente disponível? Ou existe uma constante definida em qualquer lugar nas classes fornecidas pelo JDK para o user.namenome da propriedade?
Jeff Evans

29

no Unix:

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

no Windows:

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

no Solaris:

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

49
Este código vai contra a filosofia Java de escrever uma vez, executar em qualquer lugar (introdução de código específico do sistema operacional) e, em segundo lugar, cria uma dependência da implementação Java da Sun.
Jin Kim

14
Tentar obter o nome de usuário é, por definição, específico da plataforma. Uma JVM em execução em um sistema de usuário único pode não ter um nome de usuário.
Chinmay Kanchi

8
@ChinmayKanchi: Se não houver nome de usuário, a user.namepropriedade deve ser nula. Eu concordo com @JinKim, não escreva coisas que dependem do sistema operacional.
LS

2
user.name pode ser definido na linha de comando, então depende muito de qual é o caso de uso
Alice Purcell

3
Classes em pacotes com.sun, não devem ser usadas por um desenvolvedor. Eles são internos e podem mudar no futuro.
CHiRo79 de

17

inspirado na resposta de @newacct , um código que pode ser compilado em qualquer plataforma:

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

Bom uso de reflexão :)
Zizouz212

5
Isso será interrompido no Windows, pois o método no NTSystem para obter o nome de usuário é "getName ()" e não "getUsername ()". Suponho que você possa fazer mais uma verificação e invocar o método correto. Bizarro, isso não é abstraído em um mecanismo agnóstico do SO pelo JRE?
John Mark Scarborough

1
As com.sunclasses não são acessíveis por padrão no Java 9+. Esta solução não funcionará para ele.
Thunderforge

A menos que alguma nova API tenha sido adicionada, acho que a única coisa que funcionará no Java 9 seria a solução do dfa .
Thunderforge

15

System.getProperty ("user.name") não é uma boa opção de segurança, pois essa variável de ambiente pode ser falsificada: C: \ set USERNAME = "Joe Doe" java ... // dará a você System.getProperty ("user. nome ") Você deve fazer:

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

JDK 1.5 e superior.

Eu o uso dentro de um miniaplicativo e precisa ser assinado. fonte de informação


4
Esta não é uma solução completa, pois só funciona no Windows.
LS

1
Isso também poderia ser falsificado, por exemplo, com um carregador de classe personalizado ou uma implementação personalizada com.sun.security.auth.module.NYSystemsuperior no caminho de classe? Não sei se o Java runtime tenta evitar tais explorações, mas não acho que haverá uma maneira impossível de torná-lo 'seguro', exceto executando o código em uma caixa que é inacessível para o cliente potencialmente malicioso .
bacar

4
Acabei de conseguir substituir a implementação de NTSystem.getName () usando PowerMock (que eu acredito que usa um carregador de classe personalizado), então você realmente não pode confiar em algo assim para 'segurança' ... entretanto, eu não sei como as coisas estão no mundo do applet. Eu teria pensado que, se alguém pode fornecer propriedades de sistema personalizadas, também pode fornecer classes personalizadas ou carregadores de classe personalizados.
bacar

1
-1 Porque só funciona no Windows. Você NÃO deve usar isso.
stommestack

@bacar: Eu concordo, que não se deve confiar nisso e pensar que é bastante seguro. Mas, na minha opinião, a segurança é sobre "níveis". E é muito mais fácil alterar a variável de ambiente do que fazer o powermock de um método. Em uma empresa que não é de TI, usando o NTSystem em vez da variável de ambiente, reduz pela metade a quantidade de pessoas que são capazes de executá-lo: P. Assim, você obtém um pouco mais de segurança, mas perde algumas convenções Java na estrada.
Calon

6

Usar JNA é simples:

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
Isso não funciona se você estiver conectado como um usuário de domínio, mas também houver um usuário local com o mesmo nome. getAccountByName retornará informações para o usuário local.
Dave

2

O 'set Username = "Username"' é uma substituição temporária que só existe enquanto a janela cmd ainda estiver ativa, uma vez que é eliminado, a variável perde valor. Então eu acho que

System.getProperty ("user.name");

ainda é um código curto e preciso para usar.


1

System.getenv().get("USERNAME"); - funciona no windows!

Nas propriedades do ambiente, você tem as informações de que precisa sobre o computador e o host! Estou dizendo de novo! Funciona no WINDOWS!


Sobre o quê System.getenv("username")? :)
ROMANIA_engineer

O trabalho de Doens se a VM - digamos tomcat - for iniciada como um serviço do Windows, ela retornará algo que inclui o nome do host
Deepak

0

Abaixo está uma solução APENAS PARA WINDOWS

Nos casos em que o aplicativo (como o Tomcat) é iniciado como um serviço do Windows, o System.getProperty ("user.name") ou System.getenv (). Get ("USERNAME") retorna o usuário que iniciou o serviço e não o nome de usuário conectado no momento.

Também no Java 9, as classes NTSystem etc não estarão acessíveis

Então, solução alternativa para o Windows: você pode usar wmic , então você tem que executar o comando abaixo

wmic ComputerSystem get UserName

Se disponível, isso retornará a saída do formulário:

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

Nota: Para Windows, você precisa usar cmd / c como prefixo, portanto, abaixo está um programa bruto como exemplo:

    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());
    }
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.