在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登录?Web服务器上的基本身份验证?
guerda

如果没有发布任何细节,那么什么也

对不起大家。我是Java的新手,现在很难理解。
乔治·普罗芬扎

Answers:


224
System.getProperty("user.name")

4
+1您可以打印System.properties以获取有关VM初始化的很多信息
Markus Lausberg,2009年

3
对我来说,这将打印执行VM的用户的名称。不是Java应用程序上的登录用户。
汤姆·布里托

1
是否在广泛使用的第三方库中的任何位置定义了此方法?还是在JDK提供的类中为user.name属性名称定义了一个常量?
杰夫·埃文斯

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特定代码)的哲学,其次,它对Sun的Java实现产生了依赖性。
金·金

14
根据定义,尝试获取用户名是特定于平台的。在单用户系统上运行的JVM可能根本没有用户名。
Chinmay Kanchi 2010年

8
@ChinmayKanchi:如果没有用户名,则该user.name属性应为null。我同意@JinKim,不要写与操作系统有关的东西。
LS

2
可以在命令行上设置user.name,所以这在很大程度上取决于用例
Alice Purcell 2014年

3
com.sun软件包下的类不应由开发人员使用。它们是内部的,将来可能会改变。
CHiRo79 2014年

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 '16

5
这将在Windows上中断,因为NTSystem上用于获取用户名的方法是“ getName()”而不是“ getUsername()”。我想您可以做进一步的检查,然后调用正确的方法。奇怪的是,JRE不会将其抽象为与操作系统无关的机制吗?
约翰·马克·斯卡伯勒

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及更高版本。

我在applet中使用它,并且必须对其进行签名。 信息来源


4
这不是一个完整的解决方案,因为它只能在Windows下运行。
LS

1
是否也可以使用自定义类加载器或com.sun.security.auth.module.NYSystem类路径中更高版本的自定义实现来进行欺骗?我不知道Java运行时是否试图防止这种攻击,但是我认为除了将代码运行在潜在恶意客户端无法访问的盒子上之外,没有其他方法可以使其“安全”。 。
bacar 2012年

4
我刚刚成功地使用PowerMock替换了NTSystem.getName()的实现(我相信它使用了自定义的类加载器),所以您真的不能依靠这种东西来实现“安全性”……但是我不知道小程序世界中的情况如何。我本以为,如果有人可以提供自定义系统属性,那么他们也可以提供自定义类或自定义类加载器。
bacar 2012年

1
-1因为它仅适用于Windows。您不应该使用它。
stommestack

@bacar:我同意,一个人不应该依赖于此并且认为一个人很安全。但是我认为安全性是关于“级别”的。而且,更改环境变量比模拟方法更容易。在使用NTSystem而不是环境变量的非IT公司中,能够实现该目标的人数减少了一半:P。因此,您可以获得更多的安全性,但又会丢失一些Java约定。
凯隆

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将返回本地用户的信息。
戴夫

2

“设置用户名=‘用户名’”是临时替代,只有作为CMD窗口仍上涨,一旦它被消灭后,变量失去值,只要存在。所以我认为

System.getProperty(“ user.name”);

仍然是简短而精确的代码。


1

System.getenv().get("USERNAME"); -适用于Windows!

在环境属性中,您拥有有关计算机和主机的所需信息!我再说一次!适用于WINDOWS!


System.getenv("username")呢 :)
ROMANIA_engineer

如果VM(例如tomcat)作为Windows服务启动,Doens的工作将返回包含主机名的内容
Deepak

0

以下是仅适用于WINDOWS的解决方案

如果应用程序(例如Tomcat)作为Windows服务启动,则System.getProperty(“ user.name”)或System.getenv()。get(“ USERNAME”)返回启动该服务的用户,而不是启动该服务的用户。当前登录的用户名。

同样在Java 9中将无法访问NTSystem等类

因此,适用于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());
    }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.