FTP服务器中,如果使用的是FTP协议,则用户名和密码是以明文方式传输的,如果是以SFTP 的方式,就会通过加密的方式传输。


如果服务器中的用户增加了公钥的设置,则要求客户端要有相对应的私钥。


公/私钥的产生方法可见: http://www.jcraft.com/jsch/examples/KeyGen.java.html,值得注意的是,可以产生用密码的公私钥和无密码的公私钥。


SFTP服务器: http://www.xlightftpd.com/cn/tutorial/SSH2_SFTP_Setup.html,下载后,添加虚拟服务器,添加用户,并为用户添加公钥文件,即可。


JAVA模拟一个SFTP服务器: http://mina.apache.org/sshd-project/embedding_ssh.html

http://svn.apache.org/repos/asf/mina/sshd/trunk/

public  
  void setupSftpServer(){ 
  
     SshServer sshd = SshServer.setUpDefaultServer(); 
  
     sshd.setPort(22); 
  
     sshd.setKeyPairProvider( 
  new SimpleGeneratorHostKeyProvider("hostkey.ser")); 
  

     List<NamedFactory<UserAuth>> userAuthFactories =  
  new ArrayList<NamedFactory<UserAuth>>(); 
  
     userAuthFactories.add( 
  new UserAuthNone.Factory()); 
  
     sshd.setUserAuthFactories(userAuthFactories); 
  

     sshd.setCommandFactory( 
  new ScpCommandFactory()); 
  

     List<NamedFactory<Command>> namedFactoryList =  
  new ArrayList<NamedFactory<Command>>(); 
  
     namedFactoryList.add( 
  new SftpSubsystem.Factory()); 
  
     sshd.setSubsystemFactories(namedFactoryList); 
  

      
  try { 
  
         sshd.start(); 
  
     }  
  catch (Exception e) { 
  
         e.printStackTrace(); 
  
     } 
  
 }



在这里介绍对sftp操作的一种java框架:JSch-Java Secure Channel,官方地址是: http://www.jcraft.com/jsch/



具体使用方法请看下面代码:


package jsch; 
 

import java.io.File; 
 
import java.io.FileInputStream; 
 
import java.util.Properties; 
 

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; 
 

public  
 class Test { 
 

      
 protected String host; 
 // 
 sftp服务器ip 
 
     
 protected String username; 
 // 
 用户名 
 
     
 protected String password; 
 // 
 密码 
 
     
 protected String privateKey; 
 // 
 密钥文件路径 
 
     
 protected String passphrase; 
 // 
 密钥口令 
 
     
 protected  
 int port = 22; 
 // 
 默认的sftp端口号是22 
 
 
 
      
 /** 
 
      * 获取连接
      *  
 @return 
  channel
       
 */ 
 
      
 public ChannelSftp connectSFTP() { 
 
         JSch jsch =  
 new JSch(); 
 
         Channel channel =  
 null; 
 
          
 try { 
 
              
 if (privateKey !=  
 null && !"".equals(privateKey)) { 
 
                  
 // 
 使用密钥验证方式,密钥可以使有口令的密钥,也可以是没有口令的密钥 
 
                 
 if (passphrase !=  
 null && "".equals(passphrase)) { 
 
                     jsch.addIdentity(privateKey, passphrase); 
 
                 }  
 else { 
 
                     jsch.addIdentity(privateKey); 
 
                 } 
 
             } 
 
             Session session = jsch.getSession(username, host, port); 
 
              
 if (password !=  
 null && !"".equals(password)) { 
 
                 session.setPassword(password); 
 
             } 
 
             Properties sshConfig =  
 new Properties(); 
 
             sshConfig.put("StrictHostKeyChecking", "no"); 
 // 
  do not verify host key 
 
            session.setConfig(sshConfig); 
 
              
 // 
  session.setTimeout(timeout); 
 
            session.setServerAliveInterval(92000); 
 
             session.connect(); 
 
              
 // 
 参数sftp指明要打开的连接是sftp连接 
 
            channel = session.openChannel("sftp"); 
 
             channel.connect(); 
 
         }  
 catch (JSchException e) { 
 
             e.printStackTrace(); 
 
         } 
 
          
 return (ChannelSftp) channel; 
 
     } 
 
      
 
      
 /** 
 
      * 上传文件
      * 
      *  
 @param 
  directory
      *            上传的目录
      *  
 @param 
  uploadFile
      *            要上传的文件
      *  
 @param 
  sftp
       
 */ 
 
      
 public  
 void upload(String directory, String uploadFile, ChannelSftp sftp) { 
 
          
 try { 
 
             sftp.cd(directory); 
 
             File file =  
 new File(uploadFile); 
 
             sftp.put( 
 new FileInputStream(file), file.getName()); 
 
         }  
 catch (Exception e) { 
 
             e.printStackTrace(); 
 
         } 
 
     } 
 

      
 /** 
 
      * 下载文件
      * 
      *  
 @param 
  directory
      *            下载目录
      *  
 @param 
  downloadFile
      *            下载的文件
      *  
 @param 
  saveFile
      *            存在本地的路径
      *  
 @param 
  sftp
       
 */ 
 
      
 public  
 void download(String directory, String downloadFile, 
 
             String saveFile, ChannelSftp sftp) { 
 
          
 try { 
 
             sftp.cd(directory); 
 
             sftp.get(downloadFile,saveFile); 
 
         }  
 catch (Exception e) { 
 
             e.printStackTrace(); 
 
         } 
 
     } 
 

      
 /** 
 
      * 删除文件
      * 
      *  
 @param 
  directory
      *            要删除文件所在目录
      *  
 @param 
  deleteFile
      *            要删除的文件
      *  
 @param 
  sftp
       
 */ 
 
      
 public  
 void delete(String directory, String deleteFile, ChannelSftp sftp) { 
 
          
 try { 
 
             sftp.cd(directory); 
 
             sftp.rm(deleteFile); 
 
         }  
 catch (Exception e) { 
 
             e.printStackTrace(); 
 
         } 
 
     } 
 
      
 
      
 public  
 void disconnected(ChannelSftp sftp){ 
 
          
 if (sftp !=  
 null) { 
 
              
 try { 
 
                 sftp.getSession().disconnect(); 
 
             }  
 catch (JSchException e) { 
 
                 e.printStackTrace(); 
 
             } 
 
             sftp.disconnect(); 
 
         } 
 
     } 
 
 }



在jsch自带的例子中,有一个可以根据密钥生成公钥的类,叫做UserAuthPubKey.java, 且带有图形界面。有用到的可以自己试试。