Accessing SMB2.1 or SMB3 share from java?

前端 未结 4 1730
说谎
说谎 2020-12-30 12:12

As Windows 2012R2 no longer supports the SMB1 protocol without some registry hacks has any had any success working with SMB shares in Java where only SMB2.1 or SMB3 are supp

相关标签:
4条回答
  • 2020-12-30 12:32

    Visuality Systems is currently developing JNQ which is Java-based SMB with as far as 3.1.1 support. Since the requirement contains a backwards support for Java 1.4, the development goes slowly. SMB client will be available somewhere in the coming summer, server will come later.

    0 讨论(0)
  • 2020-12-30 12:38

    I found this package that can work with SMB2 and SMB3, named smbj Take a look at this: https://github.com/hierynomus/smbj

    0 讨论(0)
  • 2020-12-30 12:38

    when use hierynomus/smbj v0.3.0, I get the exception like "ClassNotFoundException: sun.security.provider.MD4", then i use the follow code to resolve the problem.

    SmbConfig cfg = SmbConfig.builder().
                    withMultiProtocolNegotiate(true).
                    withSecurityProvider(new JceSecurityProvider(new BouncyCastleProvider())).
                    build();
    SMBClient client = new SMBClient(cfg);
    
    0 讨论(0)
  • 2020-12-30 12:54

    Expanding on @Breakidi answer, I've just used hierynomus/smbj v0.2.0 on Android and added SMB2 support. It claims support for both SMB2 and SMB3 although classes reference only SMB2 versions, not sure, maybe it is irrelevant.

    Testing

    I've tested it against box running SMB2 open in one case and then both SMB2 and SMB3 open in another. I could not disable SMB2 and test SMB3 alone though.

    Bouncycastle/Spongycastle

    There was a need to use Spongycastle in my case (most likely because of Android) as required MD4 dependency was missing from classpath. I've used it within my class that connects to SMB:

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

    Uploading file

    Make sure you set correct flags when call openFile on a DiskShare (by looking into source code off course):

    // 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();
    }
    
    0 讨论(0)
提交回复
热议问题