hierynomus smbj写入SMB共享文件报访问被拒绝问题
smbj写入SMB共享文件返回STATUS_ACCESS_DENIED异常解决
问题现象
使用smbj向共享文件夹写入文件时,代码运行触发访问被拒绝错误。已将同一共享文件夹挂载至「网络位置」,手动操作可正常在该文件夹内创建、写入文件,初步判断为代码配置参数错误。
初始实现代码如下:
public static void main(String args[]) { SMBClient client = new SMBClient(); try (Connection connection = client.connect("10.48.36.248")) { AuthenticationContext ac = new AuthenticationContext("test", "1234".toCharArray(), ""); Session session = connection.authenticate(ac); // Connect to Share try (DiskShare share = (DiskShare) session.connectShare("CCS")) { Set<FileAttributes> fileAttributes = new HashSet<>(); fileAttributes.add(FileAttributes.FILE_ATTRIBUTE_NORMAL); Set<SMB2CreateOptions> createOptions = new HashSet<>(); createOptions.add(SMB2CreateOptions.FILE_NON_DIRECTORY_FILE); createOptions.add(SMB2CreateOptions.FILE_WRITE_THROUGH); File f = share.openFile( "\\SWD\\Groups\\New Folder\\" + "Test.txt", new HashSet(Arrays.asList(new AccessMask[] { AccessMask.FILE_ADD_FILE })), fileAttributes, SMB2ShareAccess.ALL, SMB2CreateDisposition.FILE_OVERWRITE_IF, createOptions); OutputStream oStream = f.getOutputStream(); oStream.write("I am testing".getBytes()); oStream.flush(); oStream.close(); } } catch (IOException e) { e.printStackTrace(); } finally { client.close(); }
异常栈信息
Exception in thread "main" com.hierynomus.mssmb2.SMBApiException: STATUS_ACCESS_DENIED (0xc0000022): Create failed for \\10.48.36.248\CCS\SWD\Groups\New Folder\Test.txt
问题补充
路径\\10.48.36.248\CCS\SWD下的Groups文件夹为指向其他位置的快捷方式,需确认是否为该原因导致访问被拒绝,以及如何向该快捷方式指向的文件夹内写入文件。
解决方法
问题由两个配置错误共同导致,对应修改即可:
- 访问权限配置不足
代码中打开文件时仅传入了AccessMask.FILE_ADD_FILE权限,该权限仅支持在目录下创建新文件,不支持覆写已有文件、写入文件内容的操作。由于代码中使用了FILE_OVERWRITE_IF的创建 disposition,需要补充配置文件读写、属性操作相关权限,替换权限集为如下配置即可:
Set<AccessMask> accessMasks = new HashSet<>(Arrays.asList( AccessMask.FILE_READ_DATA, AccessMask.FILE_WRITE_DATA, AccessMask.FILE_APPEND_DATA, AccessMask.FILE_READ_EA, AccessMask.FILE_WRITE_EA, AccessMask.FILE_READ_ATTRIBUTES, AccessMask.FILE_WRITE_ATTRIBUTES, AccessMask.DELETE, AccessMask.SYNCHRONIZE ));
- 符号链接遍历配置缺失
路径中的Groups属于SMB协议中的重解析点(即Windows系统下的快捷方式/符号链接),smbj默认不会自动跟随重解析点遍历路径,需要额外开启两处配置:- 初始化
SMBClient时传入开启DFS支持的配置,允许自动跟随跨路径、跨共享的符号链接:
- 初始化
SMBConfig config = SmbConfig.builder() .withMultiProtocolNegotiate(true) .withDfsEnabled(true) .build(); SMBClient client = new SMBClient(config);
- 打开文件的创建选项集合中添加
FILE_OPEN_REPARSE_POINT配置,确保客户端可以正常识别路径中的重解析点:
createOptions.add(SMB2CreateOptions.FILE_OPEN_REPARSE_POINT);
排查技巧:可先直接使用
Groups指向的目标文件夹真实UNC路径替换符号链接路径测试,若此时写入正常,可先锁定问题为符号链接配置缺失,减少排查耗时。
内容的提问来源于stack exchange,提问作者Pat
相关产品推荐
相关产品推荐

