Spring Integration 6.0.1迁移后SFTP轮询认证失败问题求助
Spring Integration 6.0.1 SFTP会话创建失败:No more authentication methods available
问题描述
迁移至Java 17并将Spring Integration从5.5.15升级到6.0.1后,SFTP文件轮询器无法创建会话,抛出异常根因No more authentication methods available。仅修改了会话工厂的泛型类型从LsEntry改为org.apache.sshd.sftp.client.SftpClient.DirEntry,其余逻辑与旧代码完全一致。
旧代码(正常工作)
@Bean public SessionFactory<LsEntry> sftpSessionFactory(){ DefaultSftpSessionFactory sf = new DefaultSftpSessionFactory(); sf.setHost(serverhost); sf.setPort(portname); sf.setUser(username); Resource resource = resourceLoader.getResource(sftpKeyPrivateKey); sf.setPrivateKey(resource); sf.setPrivateKeyPassphrase(sftpKeyPrivateKeyPassword); sf.setAllowUnknownKeys(true); return new CachingSessionFactory<LsEntry> (sf); }
新代码(抛出异常)
@Bean public SessionFactory<org.apache.sshd.sftp.client.SftpClient.DirEntry> sftpSessionFactory() { DefaultSftpSessionFactory sf = new DefaultSftpSessionFactory(); sf.setHost(serverhost); sf.setPort(portname); sf.setUser(username); Resource resource = resourceLoader.getResource(sftpKeyPrivateKey); sf.setPrivateKey(resource); sf.setPrivateKeyPassphrase(sftpKeyPrivateKeyPassword); sf.setAllowUnknownKeys(true); return new CachingSessionFactory<org.apache.sshd.sftp.client.SftpClient.DirEntry>(sf); }
异常栈信息
Caused by: java.lang.IllegalStateException: failed to create SFTP Session at org.springframework.integration.sftp.session.DefaultSftpSessionFactory.getSession(DefaultSftpSessionFactory.java:291) at org.springframework.integration.sftp.session.DefaultSftpSessionFactory.getSession(DefaultSftpSessionFactory.java:67) at org.springframework.integration.file.remote.session.CachingSessionFactory$1.createForPool(CachingSessionFactory.java:85) at org.springframework.integration.file.remote.session.CachingSessionFactory$1.createForPool(CachingSessionFactory.java:82) at org.springframework.integration.util.SimplePool.doGetItem(SimplePool.java:206) at org.springframework.integration.util.SimplePool.getItem(SimplePool.java:187) ... 23 more Caused by: org.apache.sshd.common.SshException: No more authentication methods available at org.apache.sshd.common.future.AbstractSshFuture.verifyResult(AbstractSshFuture.java:127) at org.apache.sshd.client.future.DefaultAuthFuture.verify(DefaultAuthFuture.java:39) at org.apache.sshd.client.future.DefaultAuthFuture.verify(DefaultAuthFuture.java:32) at org.apache.sshd.common.future.VerifiableFuture.verify(VerifiableFuture.java:43) at org.apache.sshd.common.future.VerifiableFuture.verify(VerifiableFuture.java:68) at org.springframework.integration.sftp.session.DefaultSftpSessionFactory.initClientSession(DefaultSftpSessionFactory.java:318) at org.springframework.integration.sftp.session.DefaultSftpSessionFactory.getSession(DefaultSftpSessionFactory.java:281) ... 28 more Caused by: org.apache.sshd.common.SshException: No more authentication methods available
解决方案
1. 适配SSHD版本的私钥加载方式
Spring Integration 6.x升级了Apache SSHD依赖版本,原有的setPrivateKey(Resource)方法在新版本中可能无法正确解析私钥。需手动加载私钥为PrivateKey对象后设置:
@Bean public SessionFactory<SftpClient.DirEntry> sftpSessionFactory() { DefaultSftpSessionFactory sf = new DefaultSftpSessionFactory(); sf.setHost(serverhost); sf.setPort(portname); sf.setUser(username); sf.setAllowUnknownKeys(true); Resource resource = resourceLoader.getResource(sftpKeyPrivateKey); try (InputStream is = resource.getInputStream()) { // 加载私钥并转换为PrivateKey对象 PrivateKey privateKey = SecurityUtils.loadKeyPairIdentityProvider(is, sftpKeyPrivateKeyPassword.toCharArray()) .loadKeys() .iterator() .next(); sf.setPrivateKey(privateKey); } catch (IOException e) { throw new RuntimeException("加载SFTP私钥失败", e); } return new CachingSessionFactory<>(sf); }
2. 显式指定认证方法
新版本SSHD可能默认未启用公钥认证,需手动配置认证工厂:
sf.setClientConfigurer(client -> { // 设置私钥身份提供者 Resource resource = resourceLoader.getResource(sftpKeyPrivateKey); try (InputStream is = resource.getInputStream()) { client.setKeyIdentityProvider(SecurityUtils.loadKeyPairIdentityProvider(is, sftpKeyPrivateKeyPassword.toCharArray())); } catch (IOException e) { throw new RuntimeException("配置SFTP身份提供者失败", e); } // 显式启用公钥认证 client.setAuthenticationFactories(List.of(PublickeyAuthFactory.INSTANCE)); });
3. 兼容Java 17加密限制
Java 17对加密算法的限制更严格,若私钥为非PKCS#8格式,需转换格式;或临时添加JVM参数兼容(生产环境不推荐):
--add-opens java.base/java.security=ALL-UNNAMED
4. 简化泛型声明
避免手动指定复杂泛型,让编译器自动推断,减少类型适配问题:
return new CachingSessionFactory<>(sf);
内容的提问来源于stack exchange,提问作者Rishabh
相关产品推荐
相关产品推荐

