【问题标题】:Accessing SMB2.1 or SMB3 share from Java?从 Java 访问 SMB2.1 或 SMB3 共享?
【发布时间】:2017-05-20 13:07:09
【问题描述】:

由于 Windows 2012R2 不再支持 SMB 1 协议而没有一些注册表黑客攻击,是否有人在仅支持 SMB 2.1 或 SMB 3 的 Java 中使用 SMB 共享成功?

JCIFS 库显然只是 SMB 1,所以它已经过时了。我看到微软有一个用于 Azure 的 Java 库,但这似乎是利用服务而不是 SMB。

【问题讨论】:

    标签: java smb


    【解决方案1】:

    我发现这个包可以与 SMB2 和 SMB3 一起使用,名为 smbj 看看这个:https://github.com/hierynomus/smbj

    【讨论】:

    • 请不要仅仅发布指向某些场外资源的链接作为答案。至少在答案本身中展示how it solves the problem
    • 我从 JCIFS 切换到 smbj 并为它编写了一个包装器(以面向文件/目录的方式包含最常用的函数):github.com/swaechter/smbjwrapper
    【解决方案2】:

    扩展@Breakidi 答案,我刚刚在Android 上使用hierynomus/smbj v0.2.0 并添加了SMB2 支持。它声称支持 SMB2 和 SMB3,尽管类仅引用 SMB2 版本,不确定,也许它无关紧要。

    测试

    我已经针对在一种情况下打开 SMB2 并在另一种情况下同时打开 SMB2 和 SMB3 的盒子进行了测试。不过,我无法禁用 SMB2 并单独测试 SMB3。

    充气城堡/海绵城堡

    在我的情况下需要使用 Spongycastle(很可能是因为 Android),因为类路径中缺少所需的 MD4 依赖项。我已经在连接到 SMB 的班级中使用它:

    import org.spongycastle.jce.provider.BouncyCastleProvider;
    import java.security.Security;
    <...>
    static {
        Security.addProvider(new BouncyCastleProvider());
    }
    

    上传文件

    确保在DiskShare 上调用openFile 时设置正确的标志(通过查看源代码偏离课程):

    // required imports
    import com.hierynomus.msdtyp.AccessMask;
    import com.hierynomus.msfscc.FileAttributes;
    import com.hierynomus.mssmb2.SMB2CreateDisposition;
    import com.hierynomus.mssmb2.SMB2CreateOptions;
    import com.hierynomus.mssmb2.SMB2ShareAccess;
    import com.hierynomus.smbj.SMBClient;
    import com.hierynomus.smbj.SmbConfig;
    import com.hierynomus.smbj.auth.AuthenticationContext;
    import com.hierynomus.smbj.common.SMBApiException;
    import com.hierynomus.smbj.connection.Connection;
    import com.hierynomus.smbj.session.Session;
    import com.hierynomus.smbj.share.DiskShare;
    import com.hierynomus.smbj.share.File;
    import java.io.IOException;
    import java.io.OutputStream;
    import java.util.Arrays;
    import java.util.HashSet;
    ...
    // connection params
    String sambaDomain = null; // can be null
    String sambaUsername = "iamuploader";
    String sambaPass = "mysecret";
    String sambaIP = "192.168.1.236";
    String sambaSharedPath = "sharedfolder";
    
    ...
    // upload method
    // usage: upload("file/whithin/folder.txt", fileBytes);
    public void upload(String filename, byte[] bytes) throws IOException {
    
        SmbConfig cfg = SmbConfig.builder().build();
        SMBClient client = new SMBClient(cfg);
        Connection connection = client.connect(sambaIP);
        Session session = connection.authenticate(new AuthenticationContext(sambaUsername, sambaPass.toCharArray(), sambaDomain));
        DiskShare share = (DiskShare) session.connectShare(sambaSharedPath);
    
        // this is com.hierynomus.smbj.share.File !
        File f = null;
        int idx = filename.lastIndexOf("/");
    
        // if file is in folder(s), create them first
        if(idx > -1) {
            String folder = filename.substring(0, idx);
            try {
                if(!share.folderExists(folder)) share.mkdir(folder);
            } catch (SMBApiException ex) {
                throw new IOException(ex);
            }
    
        }
    
        // I am creating file with flag FILE_CREATE, which will throw if file exists already
        if(!share.fileExists(filename)){
            f = share.openFile(filename,
                    new HashSet<>(Arrays.asList(AccessMask.GENERIC_ALL)),
                    new HashSet<>(Arrays.asList(FileAttributes.FILE_ATTRIBUTE_NORMAL)),
                    SMB2ShareAccess.ALL,
                    SMB2CreateDisposition.FILE_CREATE,
                    new HashSet<>(Arrays.asList(SMB2CreateOptions.FILE_DIRECTORY_FILE))
            );
        }
    
        if(f == null) return null;
    
        OutputStream os = f.getOutputStream();
        os.write(bytes);
        os.close();
    }
    

    【讨论】:

      【解决方案3】:

      Visuality Systems 目前正在开发 JNQ,它是基于 Java 的 SMB,支持 3.1.1。由于该需求包含对 Java 1.4 的向后支持,因此开发进展缓慢。 SMB客户端将在即将到来的夏天的某个地方可用,服务器将在稍后出现。

      【讨论】:

        【解决方案4】:

        当使用hierynomus/smbj v0.3.0时,我得到了类似“ClassNotFoundException: sun.security.provider.MD4”的异常,然后我使用下面的代码来解决问题。

        SmbConfig cfg = SmbConfig.builder().
                        withMultiProtocolNegotiate(true).
                        withSecurityProvider(new JceSecurityProvider(new BouncyCastleProvider())).
                        build();
        SMBClient client = new SMBClient(cfg);
        

        【讨论】:

        • 你可以更好地使用直接使用BouncyCastle的BCSecurityProvider
        • 如果有人想获取共享文件夹,目前smbj不支持这个功能,那么你可以使用github上的smbj-rpc,当你发现问题时,你可以看看问题,也许是会帮你的。(比如win10 smb2)
        • 目前 smbj 不支持 smb3 只是 smb2,也许未来会
        • 或者如果你在连接时使用域名有一些错误,你可以看看这个stackoverflow.com/questions/3184463/host-is-unresolved-in-lan。祝你好运
        • 当你上传文件到多级目录时,像这样使用“parentdir\test.jpg”而不是“parentdir/test.jpg”
        【解决方案5】:

        还有一个支持 SMB2 的库:https://github.com/AgNO3/jcifs-ng

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-06-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-06-21
          • 1970-01-01
          相关资源
          最近更新 更多