关于使用JSch连接sftp服务器引发的异常

异常信息:

com.jcraft.jsch.JSchException: Session.connect: java.io.IOException: End of IO Stream Read
	at com.jcraft.jsch.Session.connect(Session.java:565)
	at com.jcraft.jsch.Session.connect(Session.java:183)

首先需要了解ssh协议的原理:https://www.cnblogs.com/zmlctt/p/3946860.html

然后开启JSch的日志打印功能,不然你是无法定位哪里错了,否则只能抓包

JSch只提供日志接口,如何打印日志,需要自己实现,代码如下

public class SftpLogger implements com.jcraft.jsch.Logger {
	    
        static Hashtable<Integer, String> name = new Hashtable<Integer, String>();
        static {
            name.put(new Integer(DEBUG), "DEBUG: ");
            name.put(new Integer(INFO), "INFO: ");
            name.put(new Integer(WARN), "WARN: ");
            name.put(new Integer(ERROR), "ERROR: ");
            name.put(new Integer(FATAL), "FATAL: ");
        }

		@Override
		public boolean isEnabled(int level) {
			return true;
		}

		@Override
        public void log(int level, String message) {
		    //这里我们就用控制台红色字体输出
            System.err.print(name.get(new Integer(level)));
            System.err.println(message);
        }
		
	}

然后开启打印

public void login(String username, String password, String host, int port) {
	    JSch.setLogger(new SftpLogger()); //设置打印类
	    JSch jsch = new JSch();
		Session session = null;
		Channel channel = null;
		try {
			session = jsch.getSession(username,host,port);
			session.setPassword(password);
			session.setConfig("StrictHostKeyChecking", "no");
			session.connect();
			channel = session.openChannel("sftp");
			channel.connect();

			//do something

		} catch (JSchException e) {
			e.printStackTrace();
		} finally {
			if(channel != null){
				channel.disconnect();
			}
			if(session != null){
				session.disconnect();
			}
		}
	}

开启打印日志后

Connecting to 198.23.12.158 port 8022
Connection established
Remote version string: SSH-2.0-OpenSSH_7.9
Local version string: SSH-2.0-JSCH-0.1.54
CheckCiphers: aes256-ctr,aes192-ctr,aes128-ctr,aes256-cbc,aes192-cbc,aes128-cbc,3des-ctr,arcfour,arcfour128,arcfour256
aes256-ctr is not available.
aes192-ctr is not available.
aes256-cbc is not available.
aes192-cbc is not available.
CheckKexes: diffie-hellman-group14-sha1,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521
diffie-hellman-group14-sha1 is not available.
CheckSignatures: ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521
SSH_MSG_KEXINIT sent
SSH_MSG_KEXINIT received
kex: server: diffie-hellman-group1-sha1,diffie-hellman-group14-sha1,diffie-hellman-group-exchange-sha1,diffie-hellman-group-exchange-sha256
kex: server: rsa-sha2-512,rsa-sha2-256,ssh-rsa,ecdsa-sha2-nistp256,ssh-ed25519
kex: server: chacha20-poly1305@openssh.com,aes128-ctr,aes192-ctr,aes256-ctr,aes128-gcm@openssh.com,aes256-gcm@openssh.com
kex: server: chacha20-poly1305@openssh.com,aes128-ctr,aes192-ctr,aes256-ctr,aes128-gcm@openssh.com,aes256-gcm@openssh.com
kex: server: umac-64-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,umac-64@openssh.com,umac-128@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1
kex: server: umac-64-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,umac-64@openssh.com,umac-128@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1
kex: server: none,zlib@openssh.com
kex: server: none,zlib@openssh.com
kex: server: 
kex: server: 
kex: client: ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group1-sha1
kex: client: ssh-rsa,ssh-dss,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521
kex: client: aes128-ctr,aes128-cbc,3des-ctr,3des-cbc,blowfish-cbc
kex: client: aes128-ctr,aes128-cbc,3des-ctr,3des-cbc,blowfish-cbc
kex: client: hmac-md5,hmac-sha1,hmac-sha2-256,hmac-sha1-96,hmac-md5-96
kex: client: hmac-md5,hmac-sha1,hmac-sha2-256,hmac-sha1-96,hmac-md5-96
kex: client: none
kex: client: none
kex: client: 
kex: client: 
kex: server->client aes128-ctr hmac-sha1 none
kex: client->server aes128-ctr hmac-sha1 none
SSH_MSG_KEX_DH_GEX_REQUEST(1024<1024<1024) sent
expecting SSH_MSG_KEX_DH_GEX_GROUP
Disconnecting from 198.23.12.158 port 8022
com.jcraft.jsch.JSchException: Session.connect: java.io.IOException: End of IO Stream Read
	at com.jcraft.jsch.Session.connect(Session.java:565)
	at com.jcraft.jsch.Session.connect(Session.java:183)

上述日志中,你会发现有is not available的字样,说明客户端不支持这些算法。为什么不支持?因为jdk环境不支持!查看JSch源码,你会发现有些算法是需要jdk8的

    config.put("diffie-hellman-group14-sha1", 
               "com.jcraft.jsch.DHG14");    // available since JDK8.
    config.put("diffie-hellman-group-exchange-sha256", 
               "com.jcraft.jsch.DHGEX256"); // available since JDK1.4.2.
                                            // On JDK8, 2048bits will be used.
    config.put("ecdsa-sha2-nistp256", "com.jcraft.jsch.jce.SignatureECDSA256");
    config.put("ecdsa-sha2-nistp384", "com.jcraft.jsch.jce.SignatureECDSA384");
    config.put("ecdsa-sha2-nistp521", "com.jcraft.jsch.jce.SignatureECDSA521");

另外也可以从日志中kex: server服务端支持的算法,kex: client客户端支持的算法可以看出他们有能够匹配的算法,所以修改使用jdk8运行应用程序,问题解决!成功后的日志输出为

Connecting to 198.23.12.158 port 8022
Connection established
Remote version string: SSH-2.0-OpenSSH_7.9
Local version string: SSH-2.0-JSCH-0.1.54
CheckCiphers: aes256-ctr,aes192-ctr,aes128-ctr,aes256-cbc,aes192-cbc,aes128-cbc,3des-ctr,arcfour,arcfour128,arcfour256
CheckKexes: diffie-hellman-group14-sha1,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521
CheckSignatures: ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521
SSH_MSG_KEXINIT sent
SSH_MSG_KEXINIT received
kex: server: diffie-hellman-group1-sha1,diffie-hellman-group14-sha1,diffie-hellman-group-exchange-sha1,diffie-hellman-group-exchange-sha256
kex: server: rsa-sha2-512,rsa-sha2-256,ssh-rsa,ecdsa-sha2-nistp256,ssh-ed25519
kex: server: chacha20-poly1305@openssh.com,aes128-ctr,aes192-ctr,aes256-ctr,aes128-gcm@openssh.com,aes256-gcm@openssh.com
kex: server: chacha20-poly1305@openssh.com,aes128-ctr,aes192-ctr,aes256-ctr,aes128-gcm@openssh.com,aes256-gcm@openssh.com
kex: server: umac-64-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,umac-64@openssh.com,umac-128@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1
kex: server: umac-64-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,umac-64@openssh.com,umac-128@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1
kex: server: none,zlib@openssh.com
kex: server: none,zlib@openssh.com
kex: server: 
kex: server: 
kex: client: ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group14-sha1,diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group1-sha1
kex: client: ssh-rsa,ssh-dss,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521
kex: client: aes128-ctr,aes128-cbc,3des-ctr,3des-cbc,blowfish-cbc,aes192-ctr,aes192-cbc,aes256-ctr,aes256-cbc
kex: client: aes128-ctr,aes128-cbc,3des-ctr,3des-cbc,blowfish-cbc,aes192-ctr,aes192-cbc,aes256-ctr,aes256-cbc
kex: client: hmac-md5,hmac-sha1,hmac-sha2-256,hmac-sha1-96,hmac-md5-96
kex: client: hmac-md5,hmac-sha1,hmac-sha2-256,hmac-sha1-96,hmac-md5-96
kex: client: none
kex: client: none
kex: client: 
kex: client: 
kex: server->client aes128-ctr hmac-sha1 none
kex: client->server aes128-ctr hmac-sha1 none
SSH_MSG_KEXDH_INIT sent
expecting SSH_MSG_KEXDH_REPLY
ssh_rsa_verify: signature true
Permanently added '198.23.12.158' (RSA) to the list of known hosts.
SSH_MSG_NEWKEYS sent
SSH_MSG_NEWKEYS received
SSH_MSG_SERVICE_REQUEST sent
SSH_MSG_SERVICE_ACCEPT received
Authentications that can continue: publickey,keyboard-interactive,password
Next authentication method: publickey
Authentications that can continue: keyboard-interactive,password
Next authentication method: keyboard-interactive
Authentications that can continue: password
Next authentication method: password
Authentication succeeded (password).
Disconnecting from 198.23.12.158 port 8022

我不想升级jdk8,是否有其他解决办法?通过看日志可以知道服务端支持的算法有:

kex: server: diffie-hellman-group1-sha1,diffie-hellman-group14-sha1,diffie-hellman-group-exchange-sha1,diffie-hellman-group-exchange-sha256

客户端支持的算法有(也可以通过JSch源码查看):

kex: client: ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group14-sha1,diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group1-sha1

那么只需要在代码中这样设置,问题即可解决。把服务端优先支持且不需要jdk8支持的算法放在前面

//diffie-hellman-group1-sha1放前面
session.setConfig("kex", "diffie-hellman-group1-sha1,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group14-sha1,diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1");

http://www.jcraft.com/jsch/ 

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
JSch是一个Java库,用于在Java程序中连接和操作SFTP服务器。通过JSch,你可以使用SFTP协议在本地和远程服务器之间传输文件。下面是一个使用JSch连接SFTP服务器的示例代码: ```java JSch jsch = new JSch(); Session session = jsch.getSession("username", "hostname", port); session.setPassword("password"); session.setConfig("StrictHostKeyChecking", "no"); session.connect(); Channel channel = session.openChannel("sftp"); channel.connect(); ChannelSftp sftp = (ChannelSftp) channel; // 在这里可以执行SFTP操作,比如上传、下载、删除文件等 channel.disconnect(); session.disconnect(); ``` 以上代码中,你需要替换`username`、`hostname`、`port`和`password`为你实际的SFTP服务器的用户名、主机名、端口和密码。通过调用`session.connect()`方法建立与服务器连接,然后通过`session.openChannel("sftp")`打开SFTP通道,最后通过`channel.connect()`连接SFTP服务器。你可以在这个连接上执行各种SFTP操作,比如上传、下载、删除文件等。最后,通过`channel.disconnect()`和`session.disconnect()`关闭连接。 如果你想读取服务器上指定路径下的所有文件,可以使用以下代码: ```java Vector<ChannelSftp.LsEntry> files = sftp.ls("/path/to/directory"); for (ChannelSftp.LsEntry file : files) { String filename = file.getFilename(); boolean isDirectory = file.getAttrs().isDir(); System.out.println(filename + " is a directory: " + isDirectory); } ``` 以上代码中,你需要将`/path/to/directory`替换为你想要读取的目录路径。通过调用`sftp.ls()`方法可以获取指定路径下的所有文件和文件夹的信息,然后通过遍历`files`列表可以获取每个文件的名称和是否是文件夹。 请注意,使用JSch连接SFTP服务器需要添加相应的依赖。你可以在你的项目的`pom.xml`文件中添加以下依赖: ```xml <dependency> <groupId>com.jcraft</groupId> <artifactId>jsch</artifactId> <version>0.1.53</version> </dependency> ``` 这样,你就可以使用JSch连接SFTP服务器并执行相应的操作了。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值