如何判断账号运行java申请是否'SYSTEM'

How to determine if account running java application is 'SYSTEM'

如何检查我的 Java 应用程序是否 运行 宁作为“系统”/“本地系统”(如 Windows 服务列表中所示)?

我试过用这个:

System.out.println("Running with user: " + System.getenv().get("USERDOMAIN") + "\" + System.getenv().get("USERNAME"));

...不过好像returnDOMAIN\COMPUTERNAME根据程序所在运行。所以它可以像 DOMAIN1\COMPUTER1 而在其他地方它是 FOO\SERVER451 并且两者仍然表示“SYSTEM”帐户。

关于背景信息,我的 Java 应用程序被包装到 Windows 服务 'Apache Commons Daemon Service Runner' 并且默认情况下它将 运行 作为“本地系统”(同样的方式如示例图片所示)。

我真的很想简化我的代码以根据用户类型打印 SYSTEMMYDOMAIN\JackTheUser...有没有办法用 Java 来实现?


编辑 20/12/02: 这就是我在 SO 军队努力寻找正确答案的同时所做的事情:

    Main:
    String username = System.getenv().get("USERNAME");
    String userdomain = System.getenv().get("USERDOMAIN");
    String servername = getComputerName();

    if (username.equalsIgnoreCase((servername + "$"))) {
        System.out.println("Running with user: 'Local System'("
                + userdomain + "\" + username + ")");
    } else {
        System.out.println("Running with user: '" + userdomain + "\"
                + username + "'");
    }
    
    Methods:
    private static String getComputerName() {
        Map<String, String> env = System.getenv();
        if (env.containsKey("COMPUTERNAME"))
            return env.get("COMPUTERNAME");
        else if (env.containsKey("HOSTNAME"))
            return env.get("HOSTNAME");
        else
            return "Unknown Host name";
    }

打印:

Running with user: 'MYDOMAIN\jokkeri'Running with user: 'Local System'(MYSERVER\SERVER_1$)

(不是一个完美的解决方案,我敢肯定在很多情况下它都行不通,但这是一个起点)


EDIT2 20/12/02: 从超级用户的这个线程中找到了一些关于 SYSTEM 帐户的有用信息:https://superuser.com/questions/265216/windows-account-ending-with

这是迄今为止我能想到的最好的

private static final String APP_NAME = "Some App";

private static final Configuration CONFIG = new Configuration() {
  public @Override AppConfigurationEntry[] getAppConfigurationEntry(String name) {
      return name.equals(APP_NAME)?
          new AppConfigurationEntry[] { new AppConfigurationEntry(
              "com.sun.security.auth.module.NTLoginModule",
              LoginModuleControlFlag.REQUIRED, Collections.emptyMap())}:
          null;
  }
};

static final boolean DEBUG = true;

public static void main(String[] args) throws LoginException {
    LoginContext lc = new LoginContext(APP_NAME, null, null, CONFIG);
    lc.login();
    final Subject subject=lc.getSubject();
    boolean isSystem = false;
    try {
        for(Principal p: subject.getPrincipals()) {
            if(DEBUG) System.out.println(p);
            if(p.toString().equals("NTSidUserPrincipal: S-1-5-18")) {
                isSystem = true;
                if(DEBUG) System.out.println("\tit's SYSTEM");
            }
        }
    }
    finally { lc.logout(); }
}

this answer 中所述,SYSTEM 是一组可以附加到不同帐户的权限。该代码遍历与当前帐户关联的所有主体并测试众所周知的 SYSTEM。

但如果您只对可打印的用户名感兴趣,您可以检查 NTUserPrincipal。

LoginContext lc = new LoginContext(APP_NAME, null, null, CONFIG);
lc.login();
final Subject subject=lc.getSubject();
try {
    String name = System.getProperty("user.name"); // just a fall-back
    for(Principal p: subject.getPrincipals()) {
        if(p.toString().startsWith("NTUserPrincipal: ")) {
            name = p.getName();
            break;
        }
    }
    System.out.println("Hello " + name);
}
finally { lc.logout(); }

如果您可以直接依赖 com.sun.security.auth 包(或 Java 9+ 中的 jdk.security.auth 模块),则可以直接使用特定的主体类型

LoginContext lc = new LoginContext(APP_NAME, null, null, CONFIG);
lc.login();
final Subject subject=lc.getSubject();
try {
    boolean system = false;
    for(NTSidUserPrincipal p: subject.getPrincipals(NTSidUserPrincipal.class)) {
        if(p.getName().equals("S-1-5-18")) {
            system = true;
            break;
        }
    }
    Set<NTUserPrincipal> up = subject.getPrincipals(NTUserPrincipal.class);
    String name = up.isEmpty()?
        System.getProperty("user.name"): up.iterator().next().getName();

    System.out.println("Hello " + name+(system? " *": ""));
}
finally { lc.logout(); }