如何使用 JSch 打开一个会话,关闭该会话,然后使用相同的凭据打开一个新会话?

How do I open a session using JSch, close that session, and then open a new one using the same credentials?

我无法使用 JSch 获取会话,关闭该会话,然后在一段时间后使用相同的凭据打开一个新会话。有人可以看看我下面的解释并提供任何建议吗?非常感谢。

我不确定我的问题是我的测试设置还是我的代码,但我遇到的问题是我无法打开、关闭,然后使用具有相同凭据的 JSch 打开新的 ssh 会话。我的测试 class 包含两个测试,这两个测试都测试下面的生产代码:

def transferFiles(String filePath, Closure fileAction) {
    def secureChannel = new JSch()

    def session = secureChannel.getSession(sftpUser, sftpHost, sftpPort)
    session.setConfig('StrictHostKeyChecking', 'no')
    session.password = sftpPass
    session.connect()

    try {
        def sftpChannel = (ChannelSftp) session.openChannel('sftp')
        sftpChannel.connect()
        try {
            processFiles(sftpChannel, filePath, fileAction)
        } finally {
            sftpChannel.exit()
        }
    } finally {
        session.disconnect()
    }
}

如果我只 运行 一个测试,那么它总是会通过,但是如果我一次 运行 整个规范,那么无论哪个测试 运行 都会通过,无论哪个第二次测试 运行s 将始终失败,但出现以下异常:

com.jcraft.jsch.JSchException: java.net.ConnectException: Connection refused
at com.jcraft.jsch.Util.createSocket(Util.java:349)
at com.jcraft.jsch.Session.connect(Session.java:215)
at com.jcraft.jsch.Session.connect(Session.java:183)
at com.simplify.acquirer.evo.service.FileTransferringService.transferFiles(FileTransferringService.groovy:32)
at com.simplify.acquirer.evo.service.DepositService.processDeposits(DepositService.groovy:8)
at com.simplify.acquirer.evo.service.FileProcessingIntegrationSpec.Deposits are successfully processed(FileProcessingIntegrationSpec.groovy:127)
Caused by: java.net.ConnectException: Connection refused
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:579)
at java.net.Socket.connect(Socket.java:528)
at java.net.Socket.<init>(Socket.java:425)
at java.net.Socket.<init>(Socket.java:208)
at com.jcraft.jsch.Util.createSocket(Util.java:343)
... 5 more

这是我的测试设置(从测试中删除了 then 块,因为它们不应该相关):

import com.jcraft.jsch.ChannelSftp
import com.jcraft.jsch.JSch
import com.jcraft.jsch.Session
import com.jcraft.jsch.UserInfo
import org.apache.sshd.SshServer
import org.apache.sshd.server.Command
import org.apache.sshd.server.CommandFactory
import org.apache.sshd.server.PasswordAuthenticator
import org.apache.sshd.server.command.ScpCommandFactory
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider
import org.apache.sshd.server.session.ServerSession
import org.apache.sshd.server.sftp.SftpSubsystem
import spock.lang.Shared
import spock.lang.Specification

class FileProcessingIntegrationSpec extends Specification {

@Shared
SshServer sshd

def setupSpec() {
    FileTransferringService.sftpUser = 'remote-username'
    FileTransferringService.sftpPass = 'remote-password'
    FileTransferringService.sftpHost = 'localhost'
    FileTransferringService.sftpPort = 22999

    sshd = SshServer.setUpDefaultServer()
    sshd.port = FileTransferringService.sftpPort
    sshd.keyPairProvider = new SimpleGeneratorHostKeyProvider('hostkey.ser')
    sshd.passwordAuthenticator = new PasswordAuthenticator() {
        public boolean authenticate(String username, String password, ServerSession session) {
            true
        }
    }
    sshd.commandFactory = new ScpCommandFactory(new CommandFactory() {
        public Command createCommand(String command) {
            System.out.println("Command: $command")
            null
        }
    })
    sshd.subsystemFactories = [new SftpSubsystem.Factory()]
    sshd.start()

    JSch sch = new JSch();
    Session session = sch.getSession("sshd", FileTransferringService.sftpHost, FileTransferringService.sftpPort);
    session.userInfo = new UserInfo() {
        public String getPassphrase() {
            null
        }

        public String getPassword() {
            'sshd'
        }

        public boolean promptPassword(String message) {
            true
        }

        public boolean promptPassphrase(String message) {
            false
        }

        public boolean promptYesNo(String message) {
            true
        }

        public void showMessage(String message) {
        }
    }
    session.connect()

    ChannelSftp c = (ChannelSftp) session.openChannel("sftp")
    c.connect()
    c.put(new FileInputStream('src/integrationTest/resources/file1.xls'), 'file1.xls')
    c.put(new FileInputStream('src/integrationTest/resources/file2.csv'), 'file2.csv')
    c.disconnect()
}

def cleanup() {
    sshd.stop()
}

def "Files are successfully processed"() {
    when:
    def result = new FileProcessingService().processFile('file1.xls')

    then:
    ...
}

def "More files are successfully processed"() {
    when:
    def result = new FileProcessingService().processFile('file2.csv')

    then:
    ...
}
}

如果需要更多信息,我会尽力提供。再次感谢。

您需要使用 cleanupSpec 而不是 cleanup。您的代码现在的工作方式是,您在 setupSpec 中创建的 sshd 服务器在第一次测试后停止,这解释了为什么第二次测试随后失败。

这可能只是一个疏忽,但为了完整起见,这里是夹具方法定义:

def setup() {}         // run before every feature method
def cleanup() {}       // run after every feature method
def setupSpec() {}     // run before the first feature method
def cleanupSpec() {}   // run after the last feature method