Java17下从ACLEntry获取SID:无需反射方案及反射异常解决
解决方案
一、无需反射的替代方法
依赖sun.nio.fs.WindowsUserPrincipals$User这类内部API存在版本兼容性风险,推荐通过Windows系统原生能力根据用户名查询SID:
方法1:调用Windows命令行工具解析输出
通过wmic命令根据用户名提取对应SID,示例代码如下:
import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.stream.Collectors; public class SidUtils { public static String getSidByUsername(String username) throws Exception { // 处理域名+用户名格式(如DOMAIN\user),提取纯用户名部分 String pureUsername = username.contains("\\") ? username.split("\\\\")[1] : username; Process process = new ProcessBuilder("wmic", "useraccount", "where", "name='" + pureUsername + "'", "get", "sid") .redirectErrorStream(true) .start(); String output = new BufferedReader(new InputStreamReader(process.getInputStream())) .lines() .collect(Collectors.joining("\n")); // 过滤输出,提取有效SID行 for (String line : output.split("\n")) { String trimmedLine = line.trim(); if (!trimmedLine.isEmpty() && !trimmedLine.equals("SID")) { return trimmedLine.toLowerCase(); } } throw new IllegalArgumentException("无法找到用户 " + username + " 的SID"); } }
使用时直接传入UserPrincipal的名称即可:
UserPrincipal userPrincipal = aclEntry.principal(); String sid = SidUtils.getSidByUsername(userPrincipal.getName());
方法2:调用Windows原生API(需引入JNA依赖)
如果追求更高性能和可靠性,可通过JNA直接调用Windows的LookupAccountNameAPI,需添加JNA相关依赖(如net.java.dev.jna:jna和net.java.dev.jna:jna-platform),通过原生API完成用户名到SID的转换,避免命令行解析的开销。
二、绕过反射异常的临时方案
若必须延续原有反射逻辑,需在Java启动参数中添加模块开放配置,允许未命名模块访问java.base下的sun.nio.fs包:
--add-opens java.base/sun.nio.fs=ALL-UNNAMED
注意:该方案依赖Java内部未公开API,未来版本存在被移除的风险,仅作为临时过渡方案使用,不推荐长期依赖。
内容的提问来源于stack exchange,提问作者Paul Curran
相关产品推荐
相关产品推荐

