java访问FTP可重用ssl通道

使用FTPSClient连接FTP下载文件,连接和登录都没有问题,但是下载文件时方法ftpsClient.listNames却报错:522 SSL connection failed; session reuse required: see require_ssl_reuse option in vsftpd.conf man page。原来是FTP的require_ssl_reuse=YES导致的, 当选项require_ssl_reuse设置为YES时,所有SSL数据连接都需要显示SSL会话重用; 证明他们知道与控制信道相同的主秘钥。联系客户把这个参数设置成NO之后果然可以下载了。
如果设置为YES就没办法了吗,当然有办法,那就是使用SSL通道重用。
但FTPSClient目前是不支持ssl通道重用的,So,不要在浪费时间了。
不过可以重写FTPSClient达到目的。重写代码如下:

import org.apache.commons.net.ftp.FTPSClient; 
import org.apache.commons.net.io.CopyStreamEvent; 
import org.apache.commons.net.io.Util; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 
 
import javax.net.ssl.SSLSession; 
import javax.net.ssl.SSLSessionContext; 
import javax.net.ssl.SSLSocket; 
import java.io.BufferedInputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.lang.reflect.Field; 
import java.lang.reflect.Method; 
import java.net.Socket; 
import java.util.Locale; 
 
 
public class SSLSessionReuseFTPSClient extends FTPSClient { 
 
    private static final Logger logger = LoggerFactory.getLogger(SSLSessionReuseFTPSClient.class); 
 
    /** 
     * @param command the command to get 
     * @param remote  the remote file name 
     * @param local   the local file name 
     * @return true if successful 
     * @throws IOException on error 
     * @since 3.1 
     */ 
    @Override 
    protected boolean _retrieveFile(String command, String remote, OutputStream local) 
            throws IOException { 
        Socket socket = _openDataConnection_(command, remote); 
 
        if (socket == null) { 
            return false; 
        } 
 
        final InputStream input; 
        input = new BufferedInputStream(socket.getInputStream()); 
 
        // Treat everything else as binary for now 
        try { 
            Util.copyStream(input, local, getBufferSize(), 
                    CopyStreamEvent.UNKNOWN_STREAM_SIZE, null, 
                    false); 
        } finally { 
            Util.closeQuietly(input); 
            Util.closeQuietly(socket); 
        } 
 
        // Get the transfer response 
        boolean ok = completePendingCommand(); 
        return ok; 
    } 
 
    @Override 
    protected void _prepareDataSocket_(final Socket socket) throws IOException { 
 
 
        if (socket instanceof SSLSocket) { 
            // Control socket is SSL 
            final SSLSession session = ((SSLSocket) _socket_).getSession(); 
            final SSLSessionContext context = session.getSessionContext(); 
            //context.setSessionCacheSize(preferences.getInteger("ftp.ssl.session.cache.size")); 
            try { 
                final Field sessionHostPortCache = context.getClass().getDeclaredField("sessionHostPortCache"); 
                sessionHostPortCache.setAccessible(true); 
                final Object cache = sessionHostPortCache.get(context); 
                final Method method = cache.getClass().getDeclaredMethod("put", Object.class, Object.class); 
                method.setAccessible(true); 
                final String key = String.format("%s:%s", socket.getInetAddress().getHostName(), 
                        String.valueOf(socket.getPort())).toLowerCase(Locale.ROOT); 
                method.invoke(cache, key, session); 
            } catch (NoSuchFieldException e) { 
                // Not running in expected JRE 
                logger.warn("No field sessionHostPortCache in SSLSessionContext", e); 
            } catch (Exception e) { 
                // Not running in expected JRE 
                logger.warn(e.getMessage()); 
            } 
        } 
    } 
 



调用方式:
private void downloadFile() {
  logger.info("进入ftp下载方法");
  SSLSessionReuseFTPSClient ftpsClient = new SSLSessionReuseFTPSClient();//("SSL", false);
  FTPClientConfig config=new FTPClientConfig();
  ftpsClient.configure(config); 
  ftpsClient.setAuthValue("TLS");  //如果FTP是AUTH TLS方式的
  ftpsClient.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out)));
  ftpsClient.setDefaultTimeout(50000);
  logger.info("开始连接ftp");
  try {
   ftpsClient.connect("127.0.0.1", "2211");
   System.out.println("Connected to ftp");
   System.out.print(ftpsClient.getReplyString());
   int reply = ftpsClient.getReplyCode();
   if (!FTPReply.isPositiveCompletion(reply)) {
    ftpsClient.disconnect();

    System.err.println("FTP server refused connection.");

    System.exit(1);
   }
   ftpsClient.login(jobContext.getRtFtpUsername(), jobContext.getRtFtpPassword());
   ftpsClient.execPBSZ(0);
   ftpsClient.execPROT("P");
   ftpsClient.setFileTransferMode(FTP.STREAM_TRANSFER_MODE);
   ftpsClient.enterLocalPassiveMode();
   
   ftpsClient.setBufferSize(1024);
            ftpsClient.setControlEncoding("GBK");
            ftpsClient.setFileType(3);
            ftpsClient.setDataTimeout(120000);
            ftpsClient.setReceiveBufferSize(100000);

   System.out.println("已经登陆FTP");
   ftpsClient.changeWorkingDirectory(jobContext.getRtFtpPath());
   FTPFile[] files = ftpsClient.listDirectories(jobContext.getRtFtpPath());
   downSuccessFileList = new ArrayList();
   downFailFileList = new ArrayList();
   downOtherFileList = new ArrayList();
   for (FTPFile ftpFile : files) {
    if (ftpFile.getName().startsWith(customerStoreCode)) {
     String[] filenames = ftpsClient.listNames(jobContext.getRtFtpPath()+ftpFile.getName());
     for (String filename : filenames) {
      if (!filename.endsWith(".xlsx")) {
       continue;
      }
      String subfilename=filename.substring(filename.lastIndexOf("/")+1, filename.length());
      File localFile = new File(jobContext.getDowDir() + File.separator + subfilename);
      OutputStream is = new FileOutputStream(localFile);
      ftpsClient.retrieveFile(filename, is);
      is.close();
      downSuccessFileList.add(subfilename);
     }
    }
   }
   ftpsClient.logout();
  } catch (Exception e) {
   logger.error("FTP下载 ->>> 下载FTP数据文件失败!!。", e);
  } finally {
   if (ftpsClient.isConnected()) { 
                    try { 
                        ftpsClient.disconnect(); 
                   } catch (IOException ioe) { 
                    logger.error("FTP下载 ->>> 下载FTP数据文件失败!!。", ioe.toString());
                    } 
                } 

  }
 }


你可能感兴趣的:(JAVA)