Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/395.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/apache/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Apache FTP客户端决定使用SSL或原始FTP_Java_Apache_Ssl_Ftp - Fatal编程技术网

Java Apache FTP客户端决定使用SSL或原始FTP

Java Apache FTP客户端决定使用SSL或原始FTP,java,apache,ssl,ftp,Java,Apache,Ssl,Ftp,在我工作的地方,我们有一个巨大的服务器,使用内部软件(使用FTP)传输文件。目前正在计划升级所有FTP以使用FTPS和SSL证书 在写这个问题的时候,我正在做一个项目,用Java/Apache更新我们的文件传输软件(它很旧) 我使用Apache软件编写了一个FTP客户端,还编写了一个非常类似的FTPS客户端。两种方法都能如期工作 但是,如果FTPS客户端尝试连接到非FTPS服务器,则会抛出SSLException。FTP客户端在这种情况下工作正常 最后,我想将两个客户端合理化为一个可以管理FTP

在我工作的地方,我们有一个巨大的服务器,使用内部软件(使用FTP)传输文件。目前正在计划升级所有FTP以使用FTPS和SSL证书

在写这个问题的时候,我正在做一个项目,用Java/Apache更新我们的文件传输软件(它很旧)

我使用Apache软件编写了一个FTP客户端,还编写了一个非常类似的FTPS客户端。两种方法都能如期工作

但是,如果FTPS客户端尝试连接到非FTPS服务器,则会抛出SSLException。FTP客户端在这种情况下工作正常

最后,我想将两个客户端合理化为一个可以管理FTP和FTPS连接的客户端

我的问题很简单:

在尝试SSL连接之前,是否有一种方法可以使用Apache/Java检测远程服务器上正在使用的协议

一个更好的解决方案是模拟cURL并尝试FTPS,然后直接使用FTP

如有任何帮助或建议,将不胜感激

下面的代码

package jtm.ftp.client;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.GeneralSecurityException;
import java.security.KeyStore;

import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLException;

import jtm.common.JtmConstants;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.commons.net.ftp.FTPSClient;
import org.apache.commons.net.util.TrustManagerUtils;
import org.apache.log4j.Logger;

public class JtmFTPSClient
{
    static Logger log = Logger.getLogger( JtmFTPSClient.class.getName( ) );   

    private static int PORT = JtmConstants.FTP_PORT;

    private static FTPSClient ftps = null;

    private static boolean IS_IMPLICIT = false;


    public static boolean getOrPut( String correlationID, String hostname, String user, String pass, String remoteFile, String localFile, String mode, String direction  )
    {        
        ftps = new FTPSClient( IS_IMPLICIT );       //look at using a constructor here perhaps - see the SWIPE FTPSClient

        boolean ftpsSuccess = false;

        log.debug( correlationID + " FTPS GET initiated" );                   

        try
        {  
            if( setSslConfig( ) == false )
            {
                return false;
            }

            String fileTermName = new File( remoteFile ).getName();                                                          

            /*
             * Configuration Section - source this from the FTPConfig object ** that needs to be made more flexible
             */

            log.info( correlationID + " FTPS Server Address : " + hostname );
            log.info( correlationID + " FTPS Port Number    : " + PORT );
            log.info( correlationID + " FTPS remoteFile     : " + remoteFile );
            log.info( correlationID + " FTPS localFile      : " + localFile );
            log.info( correlationID + " FTPS remoteTermName : " + fileTermName ); 


            // try to connect
            ftps.connect( hostname, PORT );                                                      

            /*
             *  Once connected we need to login to the server via username/password
             */
            if ( !ftps.login( user, pass ) )
            {
                log.error( correlationID + " FTPS Unable to log into : " + hostname + " with supplied credentials" );

                return false;
            }

            int reply = ftps.getReplyCode();                      

            log.debug( correlationID + " FTPS Login Reply Code : " + reply );

            /*
             * http://forus.com/csm/ftps/ trying to SSL the crap out of this client
             */
            ftps.execPBSZ( 0 );
            ftps.execPROT( "P" );

            /*
             *  FTPReply stores a set of constants for FTP reply codes.
             */
            if ( !FTPReply.isPositiveCompletion( reply ) )
            {                
                log.error( correlationID + " FTPS Not a positive reply from " + hostname + " : " + reply);                

                return false;
            }

            log.info( correlationID + " FTPS Logged into to Remote Host : " + hostname );

            ftps.enterLocalPassiveMode();

            log.debug( correlationID + " FTPS Entered Local Passive Mode");


            int xferMode = FTP.BINARY_FILE_TYPE;

            if( mode.equalsIgnoreCase("b") ) {

                xferMode = FTP.BINARY_FILE_TYPE;

            }
            else if( mode.equalsIgnoreCase("t")) {

                xferMode = FTP.ASCII_FILE_TYPE;
            }
            else
            {
                xferMode = FTP.BINARY_FILE_TYPE;
            }

            log.debug(correlationID + " Mode for FTP : " + xferMode );


            // Set the buffer size to cope with larger files
            ftps.setBufferSize( 1024 * 1024 );


            log.debug( correlationID + " FTPS Set Buffer Size to  : " + ftps.getBufferSize( ) );
            log.debug( correlationID + " FTPS Remote system type  : " + ftps.getSystemType( ) );
            log.debug( correlationID + " FTPS Remote directory is : " + ftps.printWorkingDirectory( ) );

            log.info( correlationID  + " FTPS Remote file is " + remoteFile );            

            // Get output stream - This is where the file will be downloaded to

            if(direction.equalsIgnoreCase( "get" ) )
            {
                OutputStream downloadedFile = new FileOutputStream( localFile );

                /*
                 * TODO Check that the remote file exists before download
                 * 
                 * TODO Also a check that a local copy of the file does not already exist. 
                 */                     


                /*
                 *  GET the file from the remote system ( remoteFile, downloadedFile )
                 */
                ftpsSuccess = ftps.retrieveFile( remoteFile, downloadedFile );


                /*
                 *  close output stream
                 */
                downloadedFile.close();


                log.info( correlationID + " FTPS Retrieval Complete for " + remoteFile );
            }
            else if( direction.equalsIgnoreCase("put"))
            {
                FileInputStream file = new FileInputStream( localFile );
                ftpsSuccess = ftps.storeFile(remoteFile, file );

                file.close();
            }


            if( ftpsSuccess == false )
            {
                log.error( correlationID + "FTPS Success is False" );                               
            }
        }
        catch( SSLException e )
        {
            log.error("SSLException caught ", e );

            /*
             * Do we drop down to basic FTP here and try the transfer again? 
             */
            //return JtmFTPClient.get(correlationID, hostname, user, pass, remoteFile, localFile, mode);

            ftpsSuccess = false;            

        }
        catch ( FileNotFoundException e )
        {
            log.error( correlationID + " FileNotFoundException caught ", e );


            ftpsSuccess = false;
        }       
        catch ( GeneralSecurityException e )
        {
            log.error( correlationID + " GeneralSecurityException caught ", e );

            ftpsSuccess = false;
        }
        catch ( IOException e )
        {
            log.error( correlationID + " IOException caught ", e );


            ftpsSuccess = false;
        }   
        finally
        {  
            try
            {
                ftps.logout();
                ftps.disconnect();

            }
            catch ( IOException e )
            {
                log.error(correlationID + " IOException caught closing", e );
            }
        }

        log.debug(correlationID + " FTPS result : " + ftpsSuccess );

        return ftpsSuccess;
    }




    /**
     * A Method that configures the SSL requirements when FTP'ing files to/from secure instances of UTM
     * 
     * @param  isSSL
     * @return boolean
     * @throws IOException
     * @throws GeneralSecurityException
     */
    private static boolean setSslConfig( ) throws IOException, GeneralSecurityException
    {

        String trustStorePath = JtmConstants.TRUST_STORE_PATH;
        String trustStorePass = JtmConstants.TRUST_STORE_PASS;

        String keyStorePath = JtmConstants.KEY_STORE_PATH;
        String keyStorePass = JtmConstants.KEY_STORE_PASS;

        String keyPass = JtmConstants.KEY_PASS;
        String keyAlias = JtmConstants.KEY_ALIAS;       

        boolean isSslRequired = true;


        if ( isSslRequired )
        {
            if ( trustStorePath != null && trustStorePass != null )
            {
                KeyStore ks = KeyStore.getInstance( "JKS" );
                ks.load( new FileInputStream( trustStorePath ), trustStorePass.toCharArray( ) );

                ftps.setTrustManager( TrustManagerUtils.getDefaultTrustManager( ks ) );
            }
            else
            {
                log.error( "Error setting up Trust Store" );
                log.error( "Trust Store path or trust store passord have not been supplied." );

                return false;
            }
        }
        else
        {
            ftps.setTrustManager( TrustManagerUtils.getAcceptAllTrustManager( ) );
        }


        if ( keyStorePath != null && keyStorePass != null )
        {

            File keyFile = new File( keyStorePath );

            KeyManager keyManager;

            if ( keyAlias != null )
            {
                if ( keyPass != null )
                {
                    keyManager = org.apache.commons.net.util.KeyManagerUtils
                            .createClientKeyManager( "JKS", keyFile,
                                    keyStorePass,
                                    keyAlias,
                                    keyPass );
                }
                else
                {
                    keyManager = org.apache.commons.net.util.KeyManagerUtils
                            .createClientKeyManager( keyFile, keyStorePass, keyAlias );                                            
                }
            }
            else
            {
                keyManager = org.apache.commons.net.util.KeyManagerUtils
                        .createClientKeyManager( keyFile, keyStorePass );
            }

            ftps.setKeyManager( keyManager );

            return true;
        }
        else
        {
            log.error( "Error setting up Key Store" );
            log.error( "Key Store path or key store passord have not been supplied." );

            return false;
        }
    }                    
}

不要这样做。你只是假装安全

如果您允许自动降级到不安全的连接,有很多方法可以让您被黑客攻击。至少有两种明显的方式:

  • 攻击者只需将DNS查找重定向到恶意的不安全服务器,您永远不会知道您刚刚丢失了凭据

  • 攻击者可以模拟
    AUTH
    命令失败(发生在连接安全之前)。您会自动降级为不安全连接,再次以纯文本形式向攻击者显示您的凭据


无论如何,只要尝试一下
FTPSClient
,如果
SSLException
失败,请使用
FTPClient


如果您确实需要一个用于显式TLS/SSL的好解决方案(无需重新连接),请参阅如何实现
FTPSClient.\u connectAction()。您可以重新实现它来调用基本的
FTPClient.\u connectAction()
,只需尝试
sendCommand(CMD\u AUTH,AUTH)
,而无需抛出。当然,如果
AUTH
失败,不要调用
sslnegationation()

不要这样做。你只是假装安全

如果您允许自动降级到不安全的连接,有很多方法可以让您被黑客攻击。至少有两种明显的方式:

  • 攻击者只需将DNS查找重定向到恶意的不安全服务器,您永远不会知道您刚刚丢失了凭据

  • 攻击者可以模拟
    AUTH
    命令失败(发生在连接安全之前)。您会自动降级为不安全连接,再次以纯文本形式向攻击者显示您的凭据


无论如何,只要尝试一下
FTPSClient
,如果
SSLException
失败,请使用
FTPClient


如果您确实需要一个用于显式TLS/SSL的好解决方案(无需重新连接),请参阅如何实现
FTPSClient.\u connectAction()。您可以重新实现它来调用基本的
FTPClient.\u connectAction()
,只需尝试
sendCommand(CMD\u AUTH,AUTH)
,而无需抛出。当然,如果
AUTH
失败,不要调用
sslnegationation()

是隐式的还是显式的TLS/SSL?这在自动检测方面是一个巨大的差异。它总是错误的——如果这有帮助的话?是的——我们的想法完全正确!!我们陷入困境,因为由于成本/测试和各种原因,许多系统/服务尚未升级到FTPS。理想情况下,每个人都会升级到FTPS,而这个问题根本不存在。它是隐式的还是显式的TLS/SSL?这在自动检测方面是一个巨大的差异。它总是错误的——如果这有帮助的话?是的——我们的想法完全正确!!我们陷入困境,因为由于成本/测试和各种原因,许多系统/服务尚未升级到FTPS。理想情况下,每个人都会升级到FTPS,而这个问题根本不存在。谢谢Martin,我完全同意并理解这一切的含义。恐怕我们束手无策了。今天晚些时候我会尝试你的建议,看看我如何处理它们——谢谢你。谢谢马丁,我完全同意并理解所有这些建议的含义。恐怕我们束手无策了。今天晚些时候我会尝试你的建议,看看我如何处理它们——谢谢。