4

我正在尝试使用 Apache Mina 和 JSch 编写单元测试,但我遇到了一个问题,我确信这与我在 Mina 上设置文件系统的方式有关。

这是Mina 设置代码:

sshd = SshServer.setUpDefaultServer();
sshd.setPort(8002);

sshd.setFileSystemFactory(new NativeFileSystemFactory() {
  @Override
  public void setCreateHome(boolean createHome)
  {
    super.setCreateHome(true);
  }
  @Override
  public FileSystemView createFileSystemView(final Session session) {

    String userName = session.getUsername();
    // create home if does not exist
    String homeDirStr = "/home/testusr";                    
    File homeDir = new File(homeDirStr);

    if ((!homeDir.exists()) && (!homeDir.mkdirs())) {
      System.out.println("Cannot create user home :: " + homeDirStr);
    }

    return new NativeFileSystemView(session.getUsername(), false) {
      @Override
      public String getVirtualUserDir() {        
        return "/home/testusr";        
      }
    };
  };
});

sshd.setSubsystemFactories(Arrays.<NamedFactory<Command>>asList(new SftpSubsystem.Factory()));
sshd.setCommandFactory(new ScpCommandFactory());
sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider("hostkey.ser"));
List<NamedFactory<UserAuth>> userAuthFactories = new ArrayList<NamedFactory<UserAuth>>();
    userAuthFactories.add(new UserAuthNone.Factory());
    sshd.setUserAuthFactories(userAuthFactories);
sshd.setPublickeyAuthenticator(new PublickeyAuthenticator() {
    public boolean authenticate(String username, PublicKey key, ServerSession session) {
           return true;
       }
});
sshd.start();

JS代码:

JSch jsch = new JSch();

String appPublicKey = "c:\\conf\\test_private";
jsch.addIdentity(new File(appPublicKey).getAbsolutePath());

com.jcraft.jsch.Session session = jsch.getSession("testusr","localhost", 8002);
session.setConfig("StrictHostKeyChecking", "no");
session.setTimeout(30000);
session.connect();
Channel channel = session.openChannel("sftp");
channel.connect();
ChannelSftp sftpChannel = (ChannelSftp) channel;

String filename = "c:\\temp\\test.tar.gz";
File f = new File(filename);
sftpChannel.put(new FileInputStream(f), "/home/testusr");

例外:

    4: 
    at com.jcraft.jsch.ChannelSftp.getHome(ChannelSftp.java:2403)
    at com.jcraft.jsch.ChannelSftp.getCwd(ChannelSftp.java:2412)
    at com.jcraft.jsch.ChannelSftp.remoteAbsolutePath(ChannelSftp.java:2904)
    at com.jcraft.jsch.ChannelSftp.put(ChannelSftp.java:517)
    at com.jcraft.jsch.ChannelSftp.put(ChannelSftp.java:492)
    at com.SftpServiceTest.sendFile(SftpServiceTest.java:183)
    at com.SftpServiceTest.main(SftpServiceTest.java:218)
Caused by: java.io.IOException: inputstream is closed
    at com.jcraft.jsch.ChannelSftp.fill(ChannelSftp.java:2871)
    at com.jcraft.jsch.ChannelSftp.header(ChannelSftp.java:2895)
    at com.jcraft.jsch.ChannelSftp._realpath(ChannelSftp.java:2315)
    at com.jcraft.jsch.ChannelSftp.getHome(ChannelSftp.java:2397)
    ... 6 more

我似乎找不到任何创建 FileSystemView 的好例子。希望有人可以帮助我,我已经坚持了好几天了!

提前致谢。

4

3 回答 3

1

这就是我最终在单元测试中设置 Jsch & Mina 的方式:

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration(locations = { "classpath:context.xml" }) 公共类 SftpTaskletLetterTest 扩展 AbstractAomTest {

@Autowired
private SftpTaskletLetter cut;

private SshServer sshd = null;

@Before
public void setUp() throws Exception {
    sshd = createAndStartSSHServer();
}

@After
public void tearDown() throws Exception {
    sshd.stop();
}

@Test
public void testPutAndGetFile() throws Exception {
    JSch jsch = new JSch();

    Hashtable<String, String> config = new Hashtable<>();
    JSch.setConfig(config);

    Session session = jsch.getSession("assentisftp", "127.0.0.1", 22);

    UserInfo ui = new MyUserInfo();
    session.setUserInfo(ui);
    session.connect();

    // Channel channel = session.openChannel("session"); // works
    Channel channel = session.openChannel("sftp");
    channel.connect();

    ChannelSftp sftpChannel = (ChannelSftp) channel;

    final String testFileContents = "some file contents";

    String uploadedFileName = "uploadFile";
    sftpChannel.put(new ByteArrayInputStream(testFileContents.getBytes()), uploadedFileName);

    String downloadedFileName = "downLoadFile";
    sftpChannel.get(uploadedFileName, downloadedFileName);

    File downloadedFile = new File(downloadedFileName);
    assertTrue(downloadedFile.exists());

    if (sftpChannel.isConnected()) {
        sftpChannel.exit();
    }

    if (session.isConnected()) {
        session.disconnect();
    }
}

public static SshServer createAndStartSSHServer() throws IOException {
    SshServer result = SshServer.setUpDefaultServer();
    result.setPort(22);
    result.setKeyPairProvider(new SimpleGeneratorHostKeyProvider("hostkey.ser"));
    result.setPasswordAuthenticator(new PasswordAuthenticator() {
        public boolean authenticate(String username, String password, ServerSession session) {
            return "assentisftp".equals(username);
        }
    });
    result.setSubsystemFactories(Arrays.<NamedFactory<Command>> asList(new SftpSubsystem.Factory()));
    result.start();
    return result;
}

@Override
protected MandatorType getMandator() {
    return MandatorType.MAN;
}

public static class MyUserInfo implements UserInfo {

    @Override
    public String getPassphrase() {
        return "";
    }

    @Override
    public String getPassword() {
        return "";
    }

    @Override
    public boolean promptPassword(String message) {
        return true;
    }

    @Override
    public boolean promptPassphrase(String message) {
        return true;
    }

    @Override
    public boolean promptYesNo(String message) {
        return true;
    }

    @Override
    public void showMessage(String message) {
    }
}

}

于 2015-01-22T17:16:47.223 回答
0

我认为问题出在这条线上:

sftpChannel.put(new FileInputStream(f), "/home/testusr"); 
//missing remote file name 

那应该工作:

sftpChannel.put(new FileInputStream(f), "test.tar.gz");

问候

于 2014-05-09T15:41:48.770 回答
0

我知道这是一篇旧帖子,但也许这会对某人有所帮助。

我遇到了同样的问题。我使用的是 jsch 版本 0.5.0,问题是在获取文件路径的大小并使用 String.format() 转换为数字时。我升级到另一个版本的 jsch,因为那个版本有一个错误。升级后一切正常。

于 2017-02-14T10:49:54.363 回答