sftp auth fail

今天要做一个功能:用sftp协议传文件到远程服务器,服务器是别人配置的,给出账号密码和端口2888。用的库是jsch,版本0.1.50。

根据jsch的示例,很快就改出一个实现:

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;
import com.jcraft.jsch.UserInfo;

public class Sftp {
       private static Session getSession(String user, String passwd, String host,
                   int port) throws JSchException {
            UserInfo ui = new MyUserInfo(passwd);
            JSch jsch = new JSch();
            Session session = jsch.getSession(user, host, port);
            session.setUserInfo(ui);
            session.connect();

             return session;
      }

       private static ChannelSftp getFtpChannel(Session session)
                   throws JSchException {
            Channel channel = session.openChannel( "sftp" );
            channel.connect();
            ChannelSftp c = (ChannelSftp) channel;

             return c;
      }

       public static boolean putFile(String user, String passwd, String host,
                   int port, String localeFile, String remoteFile) {
            Session session = null ;
            ChannelSftp channel = null ;
             try {
                  session = getSession(user, passwd, host, port);
                  channel = getFtpChannel(session);
                  channel.put(localeFile, remoteFile, ChannelSftp. OVERWRITE);
                  channel.quit();
            } catch (JSchException e) {
                  e.printStackTrace();
                   return false ;
            } catch (SftpException e) {
                  e.printStackTrace();
                   return false ;
            } finally {
                   clear(session, channel);
            }
             return true ;
      }

       private static void clear(Session session, Channel channel) {
             if (channel != null) {
                  channel.disconnect();
            }
             if (session != null) {
                  session.disconnect();
            }
      }

       public static void main(String[] arg) {
             boolean b = Sftp.putFile( "user" , "passwd" , "host" , 2888, "localeFile" ,
                         "remoteFile" );
            System. out .println(b);
      }

       public static class MyUserInfo implements UserInfo {
             final String passwd ;

             public MyUserInfo(String passwd) {
                   this .passwd = passwd;
            }

             public String getPassword() {
                   return passwd ;
            }

             public boolean promptYesNo(String str) {
                   // step 1, confirm accept host
                   return true ; // 接受任意服务器的指纹
            }

             public String getPassphrase() {
                   return null ;
            }

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

             public boolean promptPassword(String message) {
                   // step 2
                   return true ;
            }

             public void showMessage(String message) {
            }
      }
}

拿自己的VPS linux测试下,上传是OK的。但是上传到测试服务器时却老是出错,在建立会话时总是抛出异常:com.jcraft.jsch.JSchException : Auth fail

一开始怀疑是账号有问题,但在Xftp下是可以登录的。在shell的sftp命令下显示指定oPortoPasswordAuthentication选项也可以登录,所以就不像是账号问题了。

无奈继续google,发现很多网上代码都指定StrictHostKeyChecking选项为no,就把代码改为下面这样:

     private static Session getSession(String user, String passwd, String host,
            int port) throws JSchException {
        JSch jsch = new JSch();
        Session session = jsch.getSession(user, host, port);
        session.setConfig( "StrictHostKeyChecking" , "no" ); // 不验证host-key,验证会失败。
        session.setPassword(passwd);
        session.connect();

        return session;
    }

还真行了。

这个问题其实是因为jsch进行严格的 SSH 公钥检查导致的,禁用 SSH 远程主机的公钥检查可以方便进行自动化任务执行。如果是在shell命令行下进行的自动化任务,建议采用客户端公钥认证,也就是ssh自动登录的方式。


欢迎关注我的微信公众号: coderbee笔记,可以更及时回复你的讨论。