从 java 访问 SMB2.1 或 SMB3 共享?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/41494357/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Accessing SMB2.1 or SMB3 share from java?
提问by Moth
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 supported? the JCIFS library is apparently SMB1 only so it is out. I see that Microsoft have a Java library for Azure but this appears to be utilising services rather than SMB.
由于 Windows 2012R2 不再支持 SMB1 协议而没有一些注册表黑客,因此在仅支持 SMB2.1 或 SMB3 的 Java 中使用 SMB 共享是否有任何成功?JCIFS 库显然只是 SMB1,所以它已经出来了。我看到微软有一个用于 Azure 的 Java 库,但这似乎是在利用服务而不是 SMB。
回答by Michael Biniashvili
I found this package that can work with SMB2 and SMB3, named smbj Take a look at this: https://github.com/hierynomus/smbj
我找到了这个可以与SMB2和SMB3一起使用的包,名为smbj 看看这个:https: //github.com/hierynomus/smbj
回答by Aivaras
Expanding on @Breakidi answer, I've just used hierynomus/smbj
v0.2.0on 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.
扩展@Breakidi 答案,我刚刚在 Android 上使用了hierynomus/smbj
v0.2.0并添加了 SMB2 支持。它声称支持 SMB2 和 SMB3,尽管类仅引用 SMB2 版本,不确定,也许无关紧要。
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.
我已经在一种情况下对运行 SMB2 的盒子进行了测试,然后在另一种情况下 SMB2 和 SMB3 都打开。不过,我无法禁用 SMB2 并单独测试 SMB3。
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:
在我的情况下需要使用 Spongycastle(很可能是因为 Android),因为类路径中缺少所需的 MD4 依赖项。我在连接到 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):
确保在调用openFile
a时设置正确的标志DiskShare
(通过在课程外查看源代码):
// 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();
}
回答by Mark Rabinovich
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.
Visuality Systems 目前正在开发 JNQ,它是基于 Java 的 SMB,支持 3.1.1。由于该需求包含对 Java 1.4 的向后支持,因此开发进展缓慢。SMB 客户端将在即将到来的夏天某个地方可用,服务器将稍后提供。
回答by Vasil
when use hierynomus/smbjv0.3.0, I get the exception like "ClassNotFoundException: sun.security.provider.MD4
", then i use the follow code to resolve the problem.
使用 hierynomus/smbjv0.3.0 时,出现“ ClassNotFoundException: sun.security.provider.MD4
”之类的异常,然后我使用以下代码解决问题。
SmbConfig cfg = SmbConfig.builder().
withMultiProtocolNegotiate(true).
withSecurityProvider(new JceSecurityProvider(new BouncyCastleProvider())).
build();
SMBClient client = new SMBClient(cfg);