Nhận tên người dùng đăng nhập trong java


92

Làm cách nào để lấy tên người dùng / tên đăng nhập trong Java?

Đây là mã tôi đã thử ...

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

Tôi nhận được một SecurityExceptionkhi tôi cố gắng chạy mã này. Ai đó có thể vui lòng cho tôi biết liệu tôi có đang đi đúng hướng hay không và giúp tôi hiểu vấn đề.


3
Tôi sợ hiểu lầm bạn, nhưng tôi không hiểu câu hỏi của bạn. Tên người dùng đăng nhập nào? Đăng nhập Windows / GNU Linux? Xác thực cơ bản trên máy chủ web?
touristda

Đó là không thể hiểu được bất cứ điều gì khi không có thông tin chi tiết được đăng tải
matt b

Xin lỗi các bạn. Tôi mới làm quen với Java và bây giờ hơi khó hiểu.
George Profenza

Câu trả lời:


224
System.getProperty("user.name")

4
1 bạn có thể in System.properties để nhận được rất nhiều thông tin VM được khởi tạo với
Markus Lausberg

3
Đối với tôi, điều này in tên của người dùng thực thi VM. Không phải là người dùng đã đăng nhập trên ứng dụng java.
Tom Brito

1
Điều này có được xác định ở bất kỳ đâu trong thư viện của bên thứ ba có sẵn rộng rãi không? Hoặc có một hằng số được định nghĩa ở bất kỳ đâu trong các lớp được cung cấp của JDK cho user.nametên thuộc tính không?
Jeff Evans

29

trong Unix:

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

trong Windows:

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

ở Solaris:

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

49
Mã này đi ngược lại triết lý của Java là viết một lần, chạy ở bất kỳ đâu (giới thiệu mã cụ thể của hệ điều hành) và thứ hai, nó tạo ra sự phụ thuộc vào việc triển khai Java của Sun.
Jin Kim

14
Việc cố gắng lấy tên người dùng là theo định nghĩa dành riêng cho nền tảng. JVM chạy trên hệ thống một người dùng có thể hoàn toàn không có tên người dùng.
Chinmay Kanchi

8
@ChinmayKanchi: Nếu không có tên người dùng, thì thuộc user.nametính chỉ nên để trống. Tôi đồng ý với @JinKim, không viết những thứ phụ thuộc vào hệ điều hành.
LS

2
user.name thể được đặt trên dòng lệnh, vì vậy nó phụ thuộc rất nhiều những gì các use-case là
Alice Purcell

3
Các lớp trong gói com.sun, không nên được nhà phát triển sử dụng. Chúng là nội bộ và có thể thay đổi trong tương lai.
CHiRo79,

17

lấy cảm hứng từ câu trả lời của @newacct , một mã có thể được biên dịch trong bất kỳ nền tảng nào:

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

Tốt sử dụng phản ánh :)
Zizouz212

5
Điều này sẽ xảy ra trên Windows vì phương thức trên NTSystem để lấy tên người dùng là "getName ()" chứ không phải "getUsername ()". Tôi cho rằng bạn có thể kiểm tra thêm và sau đó gọi phương pháp phù hợp. Kỳ lạ là điều này không được JRE tóm tắt thành một cơ chế bất khả tri của hệ điều hành?
John Mark Scarborough

1
Các com.sunlớp này không thể truy cập theo mặc định trong Java 9+. Giải pháp này sẽ không hoạt động cho nó.
Thunderforge

Trừ khi một số API mới được thêm vào, tôi nghĩ thứ duy nhất sẽ hoạt động trong Java 9 sẽ là giải pháp của dfa .
Thunderforge

15

System.getProperty ("user.name") không phải là một tùy chọn bảo mật tốt vì biến môi trường đó có thể bị giả mạo: C: \ set USERNAME = "Joe Doe" java ... // sẽ cung cấp cho bạn System.getProperty ("người dùng. tên ") Bạn phải làm:

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

JDK 1.5 trở lên.

Tôi sử dụng nó trong một applet, và nó phải được ký. nguồn thông tin


4
Đây không phải là một giải pháp hoàn chỉnh, vì nó chỉ hoạt động trong Windows.
LS

1
Điều này cũng có thể bị giả mạo, ví dụ như với một trình tải lớp tùy chỉnh hoặc triển khai tùy chỉnh com.sun.security.auth.module.NYSystemcao hơn trong classpath? Tôi không biết liệu thời gian chạy Java có cố gắng ngăn chặn việc khai thác như vậy hay không, nhưng tôi không nghĩ rằng sẽ có bất kỳ cách nào dễ hiểu để làm cho nó 'an toàn' ngoại trừ bằng cách chạy mã trên một hộp không thể truy cập được đối với ứng dụng khách có khả năng độc hại .
bacar

4
Tôi vừa quản lý thành công việc thay thế việc triển khai NTSystem.getName () bằng PowerMock (mà tôi tin rằng sử dụng trình tải lớp tùy chỉnh), vì vậy bạn thực sự không thể dựa vào một cái gì đó như thế này để 'bảo mật' ... tuy nhiên tôi không biết mọi thứ như thế nào trong thế giới applet. Tôi đã nghĩ rằng nếu ai đó có thể cung cấp các thuộc tính hệ thống tùy chỉnh thì họ cũng có thể cung cấp các lớp tùy chỉnh hoặc bộ tải lớp tùy chỉnh.
bacar

1
-1 Vì nó chỉ hoạt động trên Windows. Bạn KHÔNG nên sử dụng cái này.
stommestack

@bacar: Tôi đồng ý, người ta không nên dựa vào cái này và nghĩ rằng cái này khá an toàn. Nhưng theo tôi bảo mật là về "cấp độ". Và cách dễ dàng hơn để thay đổi biến môi trường hơn là powermocking một phương thức. Trong một công ty phi CNTT, việc sử dụng NTSystem thay vì biến môi trường làm giảm hơn một nửa số lượng người có thể thực hiện nó: P. Vì vậy, bạn nhận được một chút bảo mật hơn, nhưng đến lượt nó, mất một số quy ước java trên đường.
Calon

6

Sử dụng JNA thật đơn giản:

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
Điều này không hoạt động nếu bạn đăng nhập với tư cách người dùng miền nhưng cũng có người dùng cục bộ có cùng tên. getAccountByName sẽ trả về thông tin cho người dùng cục bộ.
Dave

2

Các 'đặt Username = 'Tên đăng nhập'' là một override tạm thời mà chỉ tồn tại chừng nào các cửa sổ cmd vẫn đang gia tăng, một khi nó được giết đi, biến mất giá trị. Vì vậy, tôi nghĩ rằng

System.getProperty ("user.name");

vẫn là một mã ngắn và chính xác để sử dụng.


1

System.getenv().get("USERNAME"); - hoạt động trên cửa sổ!

Trong thuộc tính môi trường, bạn có thông tin bạn cần về máy tính và máy chủ! Tôi đang nói một lần nữa! Hoạt động trên WINDOWS!


Về System.getenv("username")thì sao? :)
ROMANIA_engineer

Việc Doens' nếu VM - nói tomcat - được bắt đầu như là một dịch vụ cửa sổ, nó sẽ trả về một cái gì đó trong đó bao gồm tên máy chủ
Deepak

0

Dưới đây là giải pháp cho CỬA SỔ CHỈ

Trong trường hợp ứng dụng (như Tomcat) được khởi động dưới dạng dịch vụ windows, System.getProperty ("user.name") hoặc System.getenv (). Get ("USERNAME") trả về người dùng đã bắt đầu dịch vụ chứ không phải tên người dùng đã đăng nhập hiện tại.

Ngoài ra trong Java 9, các lớp NTSystem vv sẽ không thể truy cập được

Vì vậy, giải pháp cho windows: Bạn có thể sử dụng wmic , vì vậy bạn phải chạy lệnh dưới đây

wmic ComputerSystem get UserName

Nếu có, nó sẽ trả về kết quả đầu ra của biểu mẫu:

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

Lưu ý: Đối với các cửa sổ, bạn cần sử dụng cmd / c làm tiền tố, vì vậy dưới đây là một chương trình thô làm ví dụ:

    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());
    }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.