Dapatkan nama pengguna login di java

92

Bagaimana saya bisa mendapatkan nama pengguna / nama login di Java?

Ini adalah kode yang telah saya coba ...

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

Saya mendapatkan SecurityExceptionketika saya mencoba menjalankan kode ini. Bisakah seseorang memberi tahu saya apakah saya sedang menuju ke arah yang benar, dan membantu saya untuk memahami masalahnya.

George Profenza
sumber
3
Saya takut salah paham, tapi saya tidak mengerti pertanyaan Anda. Nama pengguna login yang mana? Login Windows / GNU Linux? Otentikasi dasar di server web?
guerda
Tidak mungkin untuk memahami apa pun jika tidak ada detail yang diposting
matt b
Maaf kawan. Saya baru mengenal Java dan agak sulit untuk dipahami sekarang.
George Profenza

Jawaban:

225
System.getProperty("user.name")
dfa
sumber
4
+1 Anda dapat mencetak properti System.properti untuk mendapatkan banyak informasi yang menginisialisasi VM
Markus Lausberg
3
Bagi saya ini mencetak nama pengguna yang menjalankan VM. Bukan pengguna yang masuk di aplikasi java.
Tom Brito
1
Apakah ini ditentukan di mana saja di perpustakaan pihak ketiga yang tersedia secara luas? Atau apakah ada konstanta yang ditentukan di mana saja di JDK yang disediakan kelas untuk user.namenama properti?
Jeff Evans
29

di Unix:

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

di Windows:

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

di Solaris:

new com.sun.security.auth.module.SolarisSystem().getUsername()
newacct
sumber
49
Kode ini bertentangan dengan filosofi Java untuk menulis sekali, dijalankan di mana saja (pengenalan kode khusus OS), dan kedua, ini menciptakan ketergantungan pada implementasi Sun di Java.
Jin Kim
14
Mencoba mendapatkan nama pengguna berdasarkan definisi khusus platform. JVM yang berjalan pada sistem pengguna tunggal mungkin tidak memiliki nama pengguna sama sekali.
Chinmay Kanchi
8
@ChinmayKanchi: Jika tidak ada nama pengguna, maka user.nameproperti seharusnya kosong. Saya setuju dengan @JinKim, jangan menulis hal-hal yang bergantung pada OS.
Tn. Lance E Sloan
2
user.name dapat diatur pada baris perintah, jadi sangat tergantung pada kasus penggunaannya
Alice Purcell
3
Kelas di bawah paket com.sun, sebaiknya tidak digunakan oleh pengembang. Mereka bersifat internal dan dapat berubah di masa depan.
CHiRo79
17

terinspirasi oleh jawaban @newacct , kode yang dapat dikompilasi di semua platform:

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.dll
sumber
Penggunaan refleksi yang baik :)
Zizouz212
5
Ini akan rusak pada Windows karena metode pada NTSystem untuk mendapatkan nama pengguna adalah "getName ()" dan bukan "getUsername ()". Saya kira Anda dapat melakukan pemeriksaan lebih lanjut dan kemudian menggunakan metode yang benar. Anehnya ini tidak diabstraksi menjadi mekanisme OS agnostik oleh JRE?
John Mark Scarborough
1
The com.sunkelas tidak dapat diakses secara default di Jawa 9+. Solusi ini tidak akan berhasil.
Thunderforge
Kecuali beberapa API baru ditambahkan, saya pikir satu-satunya hal yang akan berfungsi di Java 9 adalah solusi dfa .
Thunderforge
15

System.getProperty ("user.name") bukanlah opsi keamanan yang baik karena variabel lingkungan tersebut dapat dipalsukan: C: \ set USERNAME = "Joe Doe" java ... // akan memberi Anda System.getProperty ("user. name ") Anda harus melakukan:

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

JDK 1.5 dan yang lebih baru.

Saya menggunakannya dalam applet, dan itu harus ditandatangani. sumber info

pdjota.dll
sumber
4
Ini bukan solusi lengkap, karena hanya berfungsi di bawah Windows.
Tn. Lance E Sloan
1
Mungkinkah ini juga dipalsukan, misalnya dengan classloader kustom atau implementasi kustom yang com.sun.security.auth.module.NYSystemlebih tinggi di classpath? Saya tidak tahu apakah runtime Java mencoba mencegah eksploitasi semacam itu, tetapi saya rasa tidak akan ada cara yang tidak dapat dilakukan untuk membuatnya 'aman' kecuali dengan menjalankan kode pada kotak yang tidak dapat diakses oleh klien yang berpotensi berbahaya .
bacar
4
Saya baru saja berhasil mengganti implementasi NTSystem.getName () menggunakan PowerMock (yang saya yakin menggunakan classloader kustom), jadi Anda benar-benar tidak dapat mengandalkan sesuatu seperti ini untuk 'keamanan' ... namun saya tidak tahu bagaimana hal-hal di dunia applet. Saya akan berpikir bahwa jika seseorang dapat menyediakan properti sistem khusus maka mereka juga dapat menyediakan kelas khusus atau pemuat kelas khusus.
bacar
1
-1 Karena hanya bekerja di Windows. Anda TIDAK harus menggunakan ini.
Stommestack
@bacar: Saya setuju, bahwa seseorang seharusnya tidak bergantung pada ini dan menganggapnya cukup aman. Tapi menurut saya keamanan adalah tentang "level". Dan jauh lebih mudah untuk mengubah variabel lingkungan daripada melakukan powermocking sebuah metode. Dalam perusahaan non-IT yang menggunakan NTSystem daripada variabel lingkungan lebih dari separuh jumlah orang yang mampu melakukannya: P. Jadi Anda mendapatkan sedikit lebih banyak keamanan, tetapi pada gilirannya kehilangan beberapa konvensi java di jalan.
Calon
6

Menggunakan JNA sederhana:

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
sumber
1
Ini tidak berfungsi jika Anda masuk sebagai pengguna domain tetapi ada juga pengguna lokal dengan nama yang sama. getAccountByName akan mengembalikan informasi untuk pengguna lokal.
Dave
2

The 'set Username = 'Username'' adalah override sementara yang hanya ada selama jendela cmd masih naik, setelah itu membunuh, variabel kehilangan nilai. Jadi saya pikir

System.getProperty ("user.name");

masih merupakan kode yang pendek dan tepat untuk digunakan.

Newtoxton
sumber
1

System.getenv().get("USERNAME"); - bekerja di jendela!

Di properti lingkungan Anda memiliki informasi yang Anda butuhkan tentang komputer dan host! Saya katakan lagi! Bekerja di WINDOWS!

Dragos Roban
sumber
Tentang apa System.getenv("username")? :)
ROMANIA_engineer
Doens bekerja jika VM - katakanlah tomcat - dimulai sebagai layanan windows, ia mengembalikan sesuatu yang menyertakan nama host
Deepak
0

Di bawah ini adalah solusi untuk WINDOWS SAJA

Dalam kasus di mana aplikasi (seperti Tomcat) dimulai sebagai layanan windows, System.getProperty ("user.name") atau System.getenv (). Get ("USERNAME") mengembalikan pengguna yang memulai layanan dan bukan nama pengguna yang masuk saat ini.

Juga di Java 9 kelas NTSystem dll tidak akan bisa diakses

Jadi solusi untuk windows: Anda dapat menggunakan wmic , jadi Anda harus menjalankan perintah di bawah ini

wmic ComputerSystem get UserName

Jika tersedia, ini akan mengembalikan keluaran dalam bentuk:

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

Catatan: Untuk windows Anda perlu menggunakan cmd / c sebagai awalan, jadi di bawah ini adalah program mentah sebagai contoh:

    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
sumber