รับชื่อผู้ใช้เข้าสู่ระบบใน java


92

ฉันจะรับชื่อผู้ใช้ / ชื่อล็อกอินใน Java ได้อย่างไร?

นี่คือรหัสที่ฉันได้ลอง ...

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

ฉันได้รับSecurityExceptionเมื่อฉันพยายามเรียกใช้รหัสนี้ ใครช่วยบอกฉันหน่อยได้ไหมว่าฉันกำลังมุ่งหน้าไปในทิศทางที่ถูกต้องและช่วยฉันเข้าใจปัญหา


3
ฉันกลัวที่จะเข้าใจคุณผิด แต่ฉันไม่เข้าใจคำถามของคุณ ชื่อผู้ใช้ล็อกอินใด ล็อกอิน Windows / GNU Linux? การรับรองความถูกต้องพื้นฐานบนเว็บเซิร์ฟเวอร์?
guerda

เป็นไปไม่ได้ที่จะเข้าใจอะไรเลยเมื่อไม่มีการโพสต์รายละเอียด
Matt b

ขอโทษนะเพื่อน. ฉันยังใหม่กับ Java และตอนนี้มันค่อนข้างยากที่จะเข้าใจ
George Profenza

คำตอบ:


225
System.getProperty("user.name")

4
+1 คุณสามารถพิมพ์ System.properties เพื่อรับข้อมูลจำนวนมากที่ VM เริ่มต้นด้วย
Markus Lausberg

3
สำหรับฉันสิ่งนี้จะพิมพ์ชื่อของผู้ใช้ที่เรียกใช้ VM ไม่ใช่ผู้ใช้ที่ล็อกอินบนแอปพลิเคชัน java
Tom Brito

1
สิ่งนี้กำหนดไว้ที่ใดก็ได้ในไลบรารีของบุคคลที่สามที่มีอยู่ทั่วไป หรือมีการกำหนดค่าคงที่ที่ใดก็ได้ใน JDK ที่จัดเตรียมคลาสสำหรับuser.nameชื่อคุณสมบัติหรือไม่
Jeff Evans

29

ใน Unix:

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

ใน Windows:

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

ใน Solaris:

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

49
รหัสนี้ขัดต่อปรัชญาของ Java ในการเขียนครั้งเดียวรันได้ทุกที่ (การแนะนำโค้ดเฉพาะ OS) และประการที่สองสร้างการพึ่งพาการใช้งาน Java ของ Sun
Jin Kim

14
การพยายามรับชื่อผู้ใช้นั้นเป็นไปตามข้อกำหนดเฉพาะแพลตฟอร์ม JVM ที่ทำงานบนระบบผู้ใช้คนเดียวอาจไม่มีชื่อผู้ใช้เลย
Chinmay Kanchi

8
@ChinmayKanchi: หากไม่มีชื่อผู้ใช้user.nameคุณสมบัติควรเป็นโมฆะ ฉันเห็นด้วยกับ @JinKim อย่าเขียนสิ่งที่ขึ้นอยู่กับระบบปฏิบัติการ
Mr. Lance E Sloan

2
user.name สามารถตั้งค่าได้ในบรรทัดคำสั่งดังนั้นจึงขึ้นอยู่กับสิ่งที่ใช้เป็นอย่างมาก
Alice Purcell

3
นักพัฒนาไม่ควรใช้คลาสภายใต้แพ็คเกจ com.sun เป็นข้อมูลภายในและอาจมีการเปลี่ยนแปลงในอนาคต
CHiRo79

17

ได้รับแรงบันดาลใจจากคำตอบของ@newacctรหัสที่สามารถรวบรวมได้ในทุกแพลตฟอร์ม:

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

ใช้การไตร่ตรองให้ดี :)
Zizouz212

5
สิ่งนี้จะหยุดทำงานบน Windows เนื่องจากวิธีการบน NTSystem ในการรับชื่อผู้ใช้คือ "getName ()" และไม่ใช่ "getUsername ()" ฉันคิดว่าคุณสามารถตรวจสอบเพิ่มเติมแล้วเรียกใช้วิธีการที่ถูกต้อง สิ่งที่แปลกประหลาดนี้ไม่ได้ถูกนำไปใช้กับกลไกการไม่เชื่อเรื่องพระเจ้าของระบบปฏิบัติการโดย JRE?
John Mark Scarborough

1
com.sunเรียนไม่สามารถเข้าถึงได้โดยเริ่มต้นใน Java 9+ วิธีนี้จะไม่ได้ผล
Thunderforge

เว้นแต่บาง API ใหม่เพิ่มผมคิดว่าสิ่งเดียวที่จะทำงานใน Java 9 จะเป็นวิธีการแก้ปัญหาของ DFA
Thunderforge

15

System.getProperty ("user.name") ไม่ใช่ตัวเลือกการรักษาความปลอดภัยที่ดีเนื่องจากตัวแปรสภาพแวดล้อมนั้นอาจถูกปลอมได้: C: \ set USERNAME = "Joe Doe" java ... // จะให้ System.getProperty ("user ชื่อ ") คุณควรทำ:

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

JDK 1.5 ขึ้นไป

ฉันใช้มันภายในแอพเพล็ตและต้องมีการลงนาม แหล่งข้อมูล


4
นี่ไม่ใช่วิธีแก้ปัญหาที่สมบูรณ์เนื่องจากใช้งานได้กับ Windows เท่านั้น
Mr. Lance E Sloan

1
สิ่งนี้อาจถูกปลอมแปลงได้เช่นกันเช่นด้วย classloader ที่กำหนดเองหรือการนำไปใช้งานที่com.sun.security.auth.module.NYSystemสูงกว่าใน classpath หรือไม่ ฉันไม่รู้ว่ารันไทม์ของ Java พยายามป้องกันการใช้ประโยชน์จากช่องโหว่ดังกล่าวหรือไม่ แต่ฉันไม่คิดว่าจะมีวิธีที่ไม่สามารถแก้ไขได้ในการทำให้ 'ปลอดภัย' ยกเว้นการรันโค้ดบนกล่องที่ไคลเอ็นต์ที่อาจเป็นอันตรายไม่สามารถเข้าถึงได้ .
bacar

4
ฉันเพิ่งประสบความสำเร็จในการแทนที่การใช้งาน NTSystem.getName () โดยใช้ PowerMock (ซึ่งฉันเชื่อว่าใช้ classloader ที่กำหนดเอง) ดังนั้นคุณจึงไม่สามารถพึ่งพาบางสิ่งเช่นนี้สำหรับ 'ความปลอดภัย' ได้ ... อย่างไรก็ตามฉันไม่รู้ สิ่งต่างๆในโลกแอพเพล็ตเป็นอย่างไร ฉันจะคิดว่าถ้ามีคนสามารถให้คุณสมบัติของระบบที่กำหนดเองได้พวกเขายังสามารถจัดหาคลาสที่กำหนดเองหรือตัวโหลดคลาสแบบกำหนดเองได้
bacar

1
-1 เนื่องจากใช้งานได้กับ Windows เท่านั้น คุณไม่ควรใช้สิ่งนี้
stommestack

@bacar: ฉันยอมรับว่าไม่ควรพึ่งพาสิ่งนี้และคิดว่าปลอดภัยดี แต่ในความคิดของฉันความปลอดภัยเป็นเรื่องของ "ระดับ" และเป็นวิธีที่ง่ายกว่าในการเปลี่ยนตัวแปรสภาพแวดล้อมมากกว่าการใช้วิธี powermocking ใน บริษัท ที่ไม่ใช่ไอทีใช้ NTSystem แทนที่จะเป็นตัวแปรสภาพแวดล้อมมากกว่าครึ่งหนึ่งของจำนวนคนที่สามารถดึงออกได้: P. ดังนั้นคุณจึงได้รับความปลอดภัยเพิ่มขึ้นเล็กน้อย แต่ก็สูญเสียการประชุมจาวาบางส่วนบนท้องถนน
Calon

6

การใช้ JNA นั้นง่ายมาก:

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
วิธีนี้ใช้ไม่ได้หากคุณเข้าสู่ระบบในฐานะผู้ใช้โดเมน แต่ยังมีผู้ใช้ในเครื่องที่มีชื่อเดียวกัน getAccountByName จะส่งคืนข้อมูลสำหรับผู้ใช้ภายในเครื่อง
Dave

2

'ตั้งชื่อผู้ใช้ = 'ชื่อผู้ใช้''เป็นแทนที่ชั่วคราวที่มีอยู่เพียงตราบเท่าที่หน้าต่าง cmd ยังคงขึ้นเมื่อมีการฆ่าตัวแปรเสียค่า ดังนั้นฉันคิดว่า

System.getProperty ("user.name");

ยังคงเป็นรหัสที่สั้นและแม่นยำในการใช้งาน


1

System.getenv().get("USERNAME"); - ทำงานบน windows!

ในคุณสมบัติสภาพแวดล้อมคุณมีข้อมูลที่คุณต้องการเกี่ยวกับคอมพิวเตอร์และโฮสต์! ฉันพูดอีกครั้ง! ทำงานบน WINDOWS!


เกี่ยวกับอะไรSystem.getenv("username")? :)
ROMANIA_engineer

Doens 'ทำงานได้หาก VM - พูดว่า tomcat - เริ่มต้นเป็นบริการ windows จะส่งคืนบางสิ่งซึ่งรวมถึงชื่อโฮสต์
Deepak

0

ด้านล่างนี้เป็นวิธีแก้ปัญหาสำหรับ WINDOWS เท่านั้น

ในกรณีที่แอปพลิเคชัน (เช่น Tomcat) เริ่มทำงานเป็นบริการของ windows ระบบ System.getProperty ("user.name") หรือ System.getenv () get ("USERNAME") จะส่งคืนผู้ใช้ที่เริ่มใช้บริการไม่ใช่ ชื่อผู้ใช้ที่เข้าสู่ระบบปัจจุบัน

นอกจากนี้ใน Java 9 จะไม่สามารถเข้าถึงคลาส NTSystem etc ได้

วิธีแก้ปัญหาสำหรับ windows: คุณสามารถใช้wmicได้ดังนั้นคุณต้องเรียกใช้คำสั่งด้านล่าง

wmic ComputerSystem get UserName

หากมีสิ่งนี้จะส่งคืนผลลัพธ์ของแบบฟอร์ม:

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

หมายเหตุ: สำหรับ windows คุณต้องใช้ cmd / c เป็นคำนำหน้าดังนั้นด้านล่างนี้เป็นโปรแกรมคร่าวๆดังตัวอย่าง:

    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());
    }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.