如何使用 JCIFS 和 apache VFS 访问 SMB URL?

Posted

技术标签:

【中文标题】如何使用 JCIFS 和 apache VFS 访问 SMB URL?【英文标题】:How do I use JCIFS with apache VFS to access an SMB URL? 【发布时间】:2012-07-21 16:45:27 【问题描述】:

我正在尝试使用 smb URL 访问本地计算机上的文件夹。 我的项目正在使用罐子:commons-vfs2-2.0.jar 和 jcifs-1.3.17.jar(以及所有其他必需的罐子)。 完整的代码是:

public static void main(String[] args) throws FileSystemException 
    jcifs.Config.registerSmbURLHandler();
    StaticUserAuthenticator auth = new StaticUserAuthenticator(<domain>,<user>,<password>);
    FileSystemOptions opts = new FileSystemOptions(); 
    DefaultFileSystemConfigBuilder.getInstance().setUserAuthenticator(opts, auth);
    FileSystemManager fs = VFS.getManager();
    FileObject smbFile = fs.resolveFile("smb://10.0.2.2/TimeOut/");
    System.out.println(smbFile.exists() + " " + smbFile.getContent().getLastModifiedTime());

我收到异常:

线程“main”中的异常 org.apache.commons.vfs2.FileSystemException:无法确定 文件类型“smb://10.0.2.2/TimeOut”。在 org.apache.commons.vfs2.provider.AbstractFileObject.getType(AbstractFileObject.java:505) 在 org.apache.commons.vfs2.provider.AbstractFileObject.exists(AbstractFileObject.java:477) 在 com.newsway.tests.VfsTest.main(VfsTest.java:23) 引起: jcifs.smb.SmbAuthException:登录失败:帐户当前已禁用。 在 jcifs.smb.SmbTransport.checkStatus(SmbTransport.java:546) 在 jcifs.smb.SmbTransport.send(SmbTransport.java:663) 在 jcifs.smb.SmbSession.sessionSetup(SmbSession.java:390) 在 jcifs.smb.SmbSession.send(SmbSession.java:218) 在 jcifs.smb.SmbTree.treeConnect(SmbTree.java:176) 在 jcifs.smb.SmbFile.doConnect(SmbFile.java:911) 在 jcifs.smb.SmbFile.connect(SmbFile.java:954) 在 jcifs.smb.SmbFile.connect0(SmbFile.java:880) 在 jcifs.smb.SmbFile.open0(SmbFile.java:972) 在 jcifs.smb.SmbFile.open(SmbFile.java:1006) 在 jcifs.smb.SmbFileInputStream.(SmbFileInputStream.java:73) 在 jcifs.smb.SmbFileInputStream.(SmbFileInputStream.java:65) 在 jcifs.smb.SmbFile.getInputStream(SmbFile.java:2844) 在 org.apache.commons.vfs2.provider.url.UrlFileObject.doGetType(UrlFileObject.java:89) 在 org.apache.commons.vfs2.provider.AbstractFileObject.getType(AbstractFileObject.java:496)

据我了解,相关部分是:登录失败:帐户当前被禁用。

尽管我的用户/密码/域很好,而且我正在做的正是 VFS 文档页面中定义的事情。

我错过了什么?

【问题讨论】:

问题已解决。我错过了 VFS 沙盒 jar 我遇到了同样的问题。当我包含 VFS 沙箱 2.1-SNAPSHOT 时,我现在得到了一个不同的异常。请看***.com/questions/27779254/… jcifs.Config.registerSmbURLHandler(); 看起来不对。它似乎使用 URL 处理程序而不是 jcifs 提供程序。可以在getManager()后面加System.out.println("prov? " + fs.hasProvider("smb"));吗? 使用commons-vfs-sandbox-2.1-SNAPSHOT System.out.println(fs.hasProvider("smb"));打印真实。似乎正确的提供程序已成功加载。 【参考方案1】:

我想我知道你的问题是什么,沙盒提供程序没有在 2.0 中自动注册。而且您还需要在解析调用中实际使用配置的身份验证属性(请参阅下面的修改源)。

我通常不使用默认文件系统管理器,而是动态注册我的提供程序,但如果您想使用自动检测,则需要将 vfs-providers.xml 添加到沙箱 JAR。

这是您使用 2.0 构建完整工作 JAR 的方式:

> git clone https://github.com/apache/commons-vfs.git -b commons-vfs2-project-2.0 vfs2.0
> cd vfs2.0
> notepad sandbox\pom.xml
> notepad sandbox\src\test\java\org\apache\commons\vfs2\provider\smb\test\StandaloneMain.java
> mvn -Pinclude-sandbox -DskipTests=true clean package dependency:tree

当您编辑 sandbox/pom.xml 时,您需要确保从 标记中删除 -SANDBOX。然后你需要添加:

  <resource>
    <directory>src/main/resources</directory>
  </resource>

到已经存在的 标记(就在第一个 LICENSE+NOTICE 之后包括第 88 行)

这是使用的测试代码:

package org.apache.commons.vfs2.provider.smb.test;

import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.commons.vfs2.FileSystemManager;
import org.apache.commons.vfs2.FileSystemOptions;
import org.apache.commons.vfs2.VFS;
import org.apache.commons.vfs2.auth.StaticUserAuthenticator;
import org.apache.commons.vfs2.impl.DefaultFileSystemConfigBuilder;


public class StandaloneMain

    public static void main(String[] args) throws FileSystemException 
        //jcifs.Config.registerSmbURLHandler();
        StaticUserAuthenticator auth = 
              new StaticUserAuthenticator("DOMAIN", "user", "SECRET");
        FileSystemOptions opts = new FileSystemOptions();
        DefaultFileSystemConfigBuilder.getInstance().setUserAuthenticator(opts, auth);
        FileSystemManager fs = VFS.getManager();
        if (!fs.hasProvider("smb")) throw new RuntimeException("Provider missing");
        System.out.println("Connecting " + args[0] + " with " + opts);
        FileObject smbFile = fs.resolveFile(args[0], opts); // added opts!
        System.out.println(smbFile.exists() + " " + smbFile.getContent().getLastModifiedTime());
    

这是执行:

> set REP=C:\Users\USERNAME\.m2\repository
> java -cp sandbox\target\commons-vfs2-sandbox-2.0.jar;^
           core\target\commons-vfs2-2.0.jar;^
           %REP%\commons-logging\commons-logging\1.1.1\commons-logging-1.1.1.jar;^
           %REP%\jcifs\jcifs\0.8.3\jcifs-0.8.3.jar;^
           sandbox\target\test-classes
       org.apache.commons.vfs2.provider.smb.test.StandaloneMain smb://HOST/Users
Jan 05, 2015 2:40:19 PM org.apache.commons.vfs2.VfsLog info
INFORMATION: Using "C:\Users\USERNAME\AppData\Local\Temp\vfs_cache" as temporary files store.
Connecting smb://eckenfels02/Users with org.apache.commons.vfs2.FileSystemOptions@27dd2ec5
true 0

【讨论】:

我刚刚对主干丢失的 vfs-provider.xml (VFS-552) 进行了修复,它将在 2.1 中【参考方案2】:

我使用不同的身份验证方法,它有效,你可以试一试。

String url = "smb://10.0.2.2/TimeOut/";   
NtlmPasswordAuthentication authen = new NtlmPasswordAuthentication(<domain>,<username>,<password>); 
SmbFile smbFile = new SmbFile(url,authen);

【讨论】:

问题是关于使用 commons vfs 执行 SMB 操作,而不是纯 JCIFS api

以上是关于如何使用 JCIFS 和 apache VFS 访问 SMB URL?的主要内容,如果未能解决你的问题,请参考以下文章

Tomcat 8.5.15 找不到 jcifs.jar

Apache VFS 错误。因为它是相对路径,并且没有提供基本 URI

如何使用 JCIFS 移动(而不是复制)文件?

Apache commons-vfs2

apache vfs 文件上传

Apache Commons VFS - 无法解析文件