如何通过Java、Python或Linux CLI获取SMB共享文件名称与权限?
我来帮你梳理几个可行的方案,针对你需要的SMB文件浏览+权限获取、全dialect支持的需求,分别从Java、Python和Java可调用的Linux CLI三个方向给出实现思路:
Java 实现方案(基于 smbj 优化)
你之前尝试过smbj,但可能没找到正确获取权限的方式——其实smbj完全支持获取文件/文件夹的权限信息,并且可以配置兼容所有SMB dialects。这里给你调整后的代码逻辑:
首先确保引入依赖(以Maven为例):
<dependency> <groupId>com.hierynomus</groupId> <artifactId>smbj</artifactId> <version>0.11.6</version> </dependency>
核心实现代码:
import com.hierynomus.msfscc.fileinformation.FileIdBothDirectoryInformation; import com.hierynomus.mssmb2.*; import com.hierynomus.smbj.SMBClient; import com.hierynomus.smbj.auth.AuthenticationContext; import com.hierynomus.smbj.connection.Connection; import com.hierynomus.smbj.session.Session; import com.hierynomus.smbj.share.DiskShare; import java.util.List; public class SmbFileBrowser { public static void main(String[] args) throws Exception { // 配置支持所有SMB dialects(覆盖SMB2到SMB3全版本) SMBClient client = new SMBClient(config -> { config.setDialects(SMBDialect.SMB2_0_2, SMBDialect.SMB2_1, SMBDialect.SMB3_0, SMBDialect.SMB3_0_2, SMBDialect.SMB3_1_1); return config; }); // 替换为你的服务器信息 String serverName = "your-server-ip"; int port = 445; String username = "your-username"; String password = "your-password"; String shareName = "your-share-name"; String targetPath = "your-target-folder-path"; try (Connection connection = client.connect(serverName, port)) { AuthenticationContext auth = new AuthenticationContext(username, password.toCharArray(), null); Session session = connection.authenticate(auth); // 连接目标共享 try (DiskShare share = (DiskShare) session.connectShare(shareName)) { // 遍历指定路径下的所有文件/文件夹 List<FileIdBothDirectoryInformation> files = share.list(targetPath); for (FileIdBothDirectoryInformation file : files) { if (file.getFileName().matches("\\.|\\.\\.")) continue; // 跳过当前/上级目录 String fileName = file.getFileName(); boolean isDirectory = file.isDirectory(); // 获取文件/文件夹的安全描述符,解析权限信息 SMB2SecurityDescriptor sd = share.getSecurityDescriptor(targetPath + "/" + fileName); List<SMB2AccessControlEntry> permissions = sd.getDacl().getAces(); // 处理权限数据,这里示例为打印信息 System.out.println("名称: " + fileName + " (是否文件夹: " + isDirectory + ")"); for (SMB2AccessControlEntry ace : permissions) { System.out.println(" 权限主体SID: " + ace.getSid().toString()); System.out.println(" 权限类型: " + (ace.getType() == SMB2AccessControlType.ACCESS_ALLOWED_ACE_TYPE ? "允许" : "拒绝")); System.out.println(" 权限掩码: " + ace.getMask()); } } } } } }
Python 实现方案(基于 impacket 优化)
你之前用impacket没满足需求,大概率是没正确解析权限信息。impacket的SMBConnection可以直接获取文件的安全描述符,进而提取权限:
from impacket.smbconnection import SMBConnection def smb_browse_with_perms(server_ip, username, password, share_name, target_path): # 建立SMB连接 conn = SMBConnection(server_ip, server_ip, sess_port=445) conn.login(username, password) # 连接目标共享 conn.connectTree(share_name) # 遍历指定路径下的文件/文件夹 file_list = conn.listPath(share_name, f"{target_path}\\*") for file in file_list: if file.get_longname() in ['.', '..']: continue file_name = file.get_longname() is_directory = file.is_directory() # 获取文件安全描述符,解析权限 sec_desc = conn.getSecurityDescriptor(share_name, f"{target_path}\\{file_name}") print(f"名称: {file_name} (是否文件夹: {is_directory})") dacl = sec_desc.get('Dacl') if dacl: for ace in dacl['Ace']: print(f" 权限主体: {ace['Sid'].formatCanonical()}") print(f" 权限类型: {'允许' if ace['AceType'] == 0 else '拒绝'}") print(f" 权限掩码: {ace['AceFlags']}") # 关闭连接 conn.close() # 调用示例 smb_browse_with_perms("your-server-ip", "your-username", "your-password", "your-share-name", "your-target-path")
Java 可调用的 Linux CLI 方案
如果偏好通过CLI工具快速实现,Java可以通过ProcessBuilder调用Samba套件的smbclient或rpcclient工具,解析输出获取权限:
用 smbclient 获取文件列表和权限
命令示例(直接在终端执行):
smbclient //your-server-ip/your-share-name -U your-username%your-password -c "ls your-target-path; getfacl your-target-path/*"
Java调用代码:
import java.io.BufferedReader; import java.io.InputStreamReader; public class SmbCliInvoker { public static void main(String[] args) throws Exception { // 替换为你的配置信息 String serverIp = "your-server-ip"; String shareName = "your-share-name"; String username = "your-username"; String password = "your-password"; String targetPath = "your-target-path"; // 构建smbclient命令 ProcessBuilder pb = new ProcessBuilder( "smbclient", "//" + serverIp + "/" + shareName, "-U", username + "%" + password, "-c", String.format("ls %s; getfacl %s/*", targetPath, targetPath) ); // 执行命令并解析输出 Process process = pb.start(); BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); String line; while ((line = reader.readLine()) != null) { // 这里可以根据输出格式,提取文件名和权限信息 System.out.println(line); } reader.close(); process.waitFor(); } }
内容的提问来源于stack exchange,提问作者zuckermanori
相关产品推荐
相关产品推荐

