Apache VFS2中setIdentityProvider()空指针异常问题修复咨询
解决Apache VFS2使用setIdentityProvider()连接SFTP时的NullPointerException问题
问题场景
使用Apache VFS2连接SFTP服务器,原setIdentities()方法已过时,改用setIdentityProvider()方法后触发NullPointerException。
原代码片段
public SFtpUtil(String hostName, String portNo, String userId, String userPwd) { sftpUri = getSftpUri(hostName, portNo, userId, userPwd); log.info("sftpUri=" + sftpUri); FileSystemOptions opts = new FileSystemOptions(); try { SftpFileSystemConfigBuilder.getInstance().setStrictHostKeyChecking(opts, "no"); SftpFileSystemConfigBuilder.getInstance().setUserDirIsRoot(opts, true); SftpFileSystemConfigBuilder.getInstance().setConnectTimeout(opts, Duration.ofSeconds(10000)); // 原setIdentities()方法可用但已过时 // SftpFileSystemConfigBuilder.getInstance().setIdentities(opts, new File[0]); // 改用setIdentityProvider()后触发NPE SftpFileSystemConfigBuilder.getInstance().setIdentityProvider(opts, new IdentityInfo(null)); log.info("setting SftpFileSystemConfigBuilder finished.");
报错堆栈
INFO | setting SftpFileSystemConfigBuilder finished. INFO | create manager INFO | manager init. org.apache.commons.vfs2.FileSystemException: Could not connect to SFTP server at "sftp://xxxxxxxxxxxxx...../". at org.apache.commons.vfs2.provider.sftp.SftpFileProvider.createSession(SftpFileProvider.java:72) at org.apache.commons.vfs2.provider.sftp.SftpFileProvider.doCreateFileSystem(SftpFileProvider.java:92) at org.apache.commons.vfs2.provider.AbstractOriginatingFileProvider.getFileSystem(AbstractOriginatingFileProvider.java:92) at org.apache.commons.vfs2.provider.AbstractOriginatingFileProvider.findFile(AbstractOriginatingFileProvider.java:71) at org.apache.commons.vfs2.provider.AbstractOriginatingFileProvider.findFile(AbstractOriginatingFileProvider.java:55) at org.apache.commons.vfs2.impl.DefaultFileSystemManager.resolveFile(DefaultFileSystemManager.java:788) at org.apache.commons.vfs2.impl.DefaultFileSystemManager.resolveFile(DefaultFileSystemManager.java:835) at lab.tmp.RunSftp.main(RunSftp.java:19) Caused by: java.lang.NullPointerException at com.jcraft.jsch.Util.checkTilde(Util.java:489) at com.jcraft.jsch.Util.fromFile(Util.java:506) at com.jcraft.jsch.KeyPair.load(KeyPair.java:540) at com.jcraft.jsch.IdentityFile.newInstance(IdentityFile.java:40) at com.jcraft.jsch.JSch.addIdentity(JSch.java:423) at org.apache.commons.vfs2.provider.sftp.IdentityInfo.addIdentity(IdentityInfo.java:87) at org.apache.commons.vfs2.provider.sftp.SftpClientFactory.addIdentity(SftpClientFactory.java:117) at org.apache.commons.vfs2.provider.sftp.SftpClientFactory.addIdentities(SftpClientFactory.java:104) at org.apache.commons.vfs2.provider.sftp.SftpClientFactory.createConnection(SftpClientFactory.java:154) at org.apache.commons.vfs2.provider.sftp.SftpFileProvider.createSession(SftpFileProvider.java:65) ... 8 more
问题原因
传入new IdentityInfo(null)时,IdentityInfo会尝试加载一个空路径的密钥文件,底层JSch库在处理空路径时触发NullPointerException。原代码中setIdentities(opts, new File[0])的作用是不加载任何密钥文件,仅使用密码认证,但改用IdentityInfo(null)并没有达到相同效果。
解决方案
根据需求选择以下任一方式修改:
方案1:使用空文件数组创建IdentityInfo
直接传入空的文件数组给IdentityInfo,替代原new File[0]的逻辑:
// 替换原来的new IdentityInfo(null) SftpFileSystemConfigBuilder.getInstance().setIdentityProvider(opts, new IdentityInfo(new File[0], null));
IdentityInfo会遍历空数组,不加载任何密钥文件,与原setIdentities(new File[0])行为一致。
方案2:自定义空实现的IdentityProvider
如果不需要任何密钥认证,直接提供一个不执行任何操作的IdentityProvider实现:
SftpFileSystemConfigBuilder.getInstance().setIdentityProvider(opts, new IdentityProvider() { @Override public void addIdentity(JSch jsch) throws JSchException { // 不添加任何身份信息,仅使用密码认证 } });
方案3:不设置IdentityProvider
如果你的SFTP连接仅依赖密码认证,且不需要禁用默认密钥加载逻辑,可以直接删除setIdentityProvider()的调用,让VFS2使用默认处理逻辑。
内容的提问来源于stack exchange,提问作者Ryan
相关产品推荐
相关产品推荐

