`
410063005
  • 浏览: 179990 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

Java SSLSocket的使用之二---让edtFTPj支持FTPS

 
阅读更多

免费版的edtFTPj不支持FTPS等安全协议, 所以不能访问基于TLS/SSL FTP服务器。最近对SSL有了些概念,项目也使用过edtFTPj库,所以尝试给这个库添加TLS/SSL支持,就当是个练习。

 

1. commons-net的FTP

 

commons-net包支持TLS/SSL FTP,首先参考它的实现。


FTP:实现了基本的FTP命令,

FTPClient:对FTP中的基本FTP命令进行封装

FTPSClient: 提供 TLS/SSL FTP功能. 

 

FTP、FTP、FTPSClient继承了SocketClient类的connect()方法, 该方法主要是发起到远端的连接并调用_connectAction_()方法。。 这三个子类重写了_connectAction_()方法。

 

 

    // SocketClient.java
    public void connect(InetAddress host, int port,
                        InetAddress localAddr, int localPort)
    throws SocketException, IOException
    {
        _socket_ = _socketFactory_.createSocket();
        if (receiveBufferSize != -1) {
            _socket_.setReceiveBufferSize(receiveBufferSize);
        }
        if (sendBufferSize != -1) {
            _socket_.setSendBufferSize(sendBufferSize);
        }
        _socket_.bind(new InetSocketAddress(localAddr, localPort));
        _socket_.connect(new InetSocketAddress(host, port), connectTimeout);
        _connectAction_();
    }

 

 

 

 

    
    // FTPSClient.java
    protected void _connectAction_() throws IOException {
        // Implicit mode.
        if (isImplicit) {
            sslNegotiation();
        }
        super._connectAction_();
        // Explicit mode.
        if (!isImplicit) {
            execAUTH();
            sslNegotiation();
        }
    }

 

 FTPSClient重写_connectAction_方法:如果isImplicit为false, 则执行AUTH命令并开始SSL握手;否则直接开始SSL握手。

 

 

    // FTPSClient
    protected void sslNegotiation() throws IOException {
        plainSocket = _socket_;
        initSslContext();

        SSLSocketFactory ssf = context.getSocketFactory();
        String ip = _socket_.getInetAddress().getHostAddress();
        int port = _socket_.getPort();
        SSLSocket socket =
            (SSLSocket) ssf.createSocket(_socket_, ip, port, false);
        socket.setEnableSessionCreation(isCreation);
        socket.setUseClientMode(isClientMode);
        // server mode
        if (!isClientMode) {
            socket.setNeedClientAuth(isNeedClientAuth);
            socket.setWantClientAuth(isWantClientAuth);
        }

        if (protocols != null) {
            socket.setEnabledProtocols(protocols);
        }
        if (suites != null) {
            socket.setEnabledCipherSuites(suites);
        }
        socket.startHandshake();

        _socket_ = socket;
        _controlInput_ = new BufferedReader(new InputStreamReader(
                socket .getInputStream(), getControlEncoding()));
        _controlOutput_ = new BufferedWriter(new OutputStreamWriter(
                socket.getOutputStream(), getControlEncoding()));
    }

 FTPSClient的sslNegotiation()方法说白了就是用一个已经连接到远程FTP服务器的Socket来创建一个SSLSocket,并替换原来的_socket_成员变量

 

 

2. edtFTPj添加FTPS支持

按照上面的思路给edtFTPj添加 FTPS支持。首先看edtFTPj主要的类,(蓝色是我添加的类)

 


我们写的应用使用edtFTPj包提供的FileTransferClient作为FTP客户端。一般这样使用

 

FileTransferClient client = new FileTransferClient();

 得到一个不支持TLS/SSL的FTP客户端。 

 

 

根据以上用法, 主要作以下修改:

1. 实现一个继承自FTPClient的类FTPSClient

2. 实现一个承自FTPControlSocket的类FTPSControlSocket

3. 实现一个SSLSocket的代理MySSLSocket, 这个类同时继承StreamSocket

4. 修改FileTransferClient的构造方法, 通过一个参数来区分是生成FTPClient还是FTPSClient对象

 

基本上,对原有代码的修改只有一处,其他位置都是扩展。 比较关键的两处代码如下

 

 

public class FTPSClient extends FTPClient {

	@Override
	public void connect() throws IOException, FTPException {

		checkConnection(false);

		if (remoteAddr == null)
			remoteAddr = InetAddress.getByName(remoteHost);

		// 创建Socket
		FTPSControlSocket sock = new FTPSControlSocket(remoteAddr, controlPort,
				timeout, controlEncoding, messageListener);
		initialize(sock);

		// 在Socket上发出第一条命令AUTH TLS
		System.out.println("send AUTH TLS");

		lastReply = control.sendCommand("AUTH TLS");
		if (!"234".equals(lastReply.getReplyCode())) {
			System.err.println("err");
			throw new IOException();
		}

		// 创建SSLSocket
		StreamSocket ss = MySSLSocket.createSSLSocket(sock.getControlSock(),
				remoteAddr, controlPort, timeout);

		// 用SSLSocket替换原来的的Socket
		sock.setControlSock(ss);

		sock.initStreams();
	}

 这段代码所做的工作类似于前面提到的sslNegotiation方法

 

 

 

public class MySSLSocket implements StreamSocket {

	private SSLSocket sslSocket;
	protected String remoteHostname;

	private MySSLSocket(SSLSocket sslSocket) {
		this.sslSocket = sslSocket;
	}

	public static MySSLSocket createSSLSocket(Socket socket, InetAddress host,
			int port, int timeout) throws IOException {
		SSLSocket sock = getSSLSocket(socket, host.getHostName(), port);
		if (null == sock) {
			throw new IOException("null SSLSocket");
		}

		// 注意: 已连接, 不用再次连接
		// sock.connect(addr, timeout);
		return new MySSLSocket(sock);
	}

	private static SSLSocket getSSLSocket(Socket socket, String host, int port) {
		long now = System.currentTimeMillis();
		try {
			SSLContext sslContext = SSLContext.getInstance("SSL");
			sslContext.init(null,
					new TrustManager[] { new MyX509TrustManager() }, null);

			SSLSocket sslSocket = (SSLSocket) sslContext.getSocketFactory()
					.createSocket(socket, host, port, false);
			sslSocket.setEnableSessionCreation(true);
			sslSocket.setUseClientMode(true);
			System.out.println(System.currentTimeMillis() - now);
			now = System.currentTimeMillis();
			sslSocket.startHandshake();

			System.out.println("shakehand takes"
					+ (System.currentTimeMillis() - now));
			return sslSocket;
		} catch (KeyManagementException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

 

 这段代码主要是通过一个已经连接到FTP服务器的Socket(控制连接)来创建一个SSLSocket,之后FTPSClient使用这个SSLSocket与FTP服务器交互。

 

 

	public static void main(String[] args) throws FTPException, IOException {
		// 使用自己添加的构造函数, 获取一个支持FTPS的 FileTransferClient
		FileTransferClient client = new FileTransferClient(FTPType.FTPS);

		client.setRemoteHost("10.204.80.48");
		client.setRemotePort(21);
		client.setUserName("tom");
		client.setPassword("123456");

		// 二进制传输模式
		client.setContentType(FTPTransferType.BINARY);
		// 控制信道上的字符集为utf-8
		client.getAdvancedSettings().setControlEncoding("utf-8");
		// 不要自动登录
		client.getAdvancedSettings().setAutoLogin(false);
		client.getAdvancedFTPSettings().setConnectMode(FTPConnectMode.PASV);

		try {
			client.connect();

			client.manualLogin();

			// 遍历当前目录
			for (String string : client.directoryNameList()) {
				System.out.println(string);
			}

			client.changeDirectory("data");

			// 遍历data目录
			for (String string : client.directoryNameList()) {
				System.out.println(string);
			}

			client.uploadFile("c:\\a.txt", "cm.txt");
			System.out.println("upload!!");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

 

 简单验证了下FTPSClient的功能, 可以登录、切换目录、显示目录列表、上传文件。用Wireshark抓包看了下, 控制连接和数据连接上数据果然都加密了。

 

3. 遗留的问题

 

(1) 登录很慢。 对比了下, 用commons-net包里面的FTPSClient,登录非常快。 

(2) 数据连接也加密了吗? 还需要再看看代码

 

 

  • 大小: 30.7 KB
  • 大小: 42.2 KB
  • 大小: 42.1 KB
分享到:
评论
1 楼 zxjlwt 2015-09-01  
学习了。

http://surenpi.com

相关推荐

    Java SSLSocket的使用

    Java SSLSocket是Java平台中用于处理安全套接字层(SSL)或传输层安全(TLS)协议的类,它是Socket类的一个子类,提供了在客户端和服务器之间进行加密通信的能力。SSL和TLS协议主要用于保护网络数据传输,防止数据被...

    Java中SSLSocket应用教程和代码

    在Java编程语言中,SSLSocket(Secure Sockets Layer Socket)是用于实现安全网络通信的重要组件,它基于SSL/TLS协议栈,为应用程序提供加密的数据传输服务。本教程将深入探讨Java中的SSLSocket应用,包括其基本概念...

    perl-IO-Socket-SSL-1.94-7.el7.noarch.rpm

    官方离线安装包,亲测可用。使用rpm -ivh [rpm完整包名] 进行安装

    Java ssl socket 双向认证

    在Java中,我们可以使用JSSE(Java Secure Socket Extension)库来实现SSL连接。双向认证,也称为客户端和服务器端的相互认证,是一种更高级的安全策略,它要求不仅服务器需要验证客户端的身份,客户端也需要验证...

    java-socket大文件上传-含客户端和服务端

    在Java编程中,Socket是网络通信的基础,常用于实现客户端(Client)与服务器端(Server)之间的双向通信。本项目“java-socket大文件上传-含客户端和服务端”旨在演示如何利用Java Socket API来实现大文件的上传...

    基于ssl的Java的socket网络通信

    在Java中,我们可以使用JSSE(Java Secure Socket Extension)来实现基于SSL的网络通信。 首先,要创建一个SSL Socket,我们需要配置一个SSLContext对象。SSLContext是SSL/TLS协议的核心,它管理密钥和证书,以及...

    Java Socket 实现SMTP邮件发送,支持SSL/TSL

    在本案例中,我们将关注如何使用Java Socket来实现SMTP(Simple Mail Transfer Protocol)邮件发送,并支持SSL(Secure Sockets Layer)和TLS(Transport Layer Security)安全协议。 SMTP是一种互联网标准,用于在...

    commons-net-1.4.1.jar、jakarta-oro-2.0.8.jar、edtftpj.jar

    在1.4.1版本中,它包含FTP客户端和服务器的API,支持主动和被动模式,以及SSL/TLS加密的FTP连接。开发者可以使用这个库来轻松地在Java应用程序中实现FTP文件上传、下载和管理功能。 2. **jakarta-oro-2.0.8.jar**:...

    SSL+socket 详解-概念

    JSSE(Java Secure Socket Extension)是Java的一个扩展库,它提供了一套API,允许Java应用程序实现SSL/TLS协议,从而为数据传输提供端到端的安全性。JSSE支持服务器和客户端之间的安全通信,能够防止数据在传输过程...

    java 采用ssl的socket交互

    详细介绍了java如何使用SSL来进行socket通信了 最主要的是介绍了如何使用keytool来生成.keystore文件 ps:设置一分是希望那些刚入门或则对csdn访问不多的朋友 多花点时间 表面上市搞积分 事实上是有帮助的。 如果你...

    java socket使用加密协议传输对象

    在Java中,实现这种加密通信的方式之一就是使用SSLSocket。 #### SSLSocket的使用 在Java中,SSLSocket是Socket的一个子类,专门用于支持SSL/TLS加密的网络通信。下面,我们将详细介绍如何在Java Socket中使用SSL...

    基于 MINA 的 TLS/SSL NIO Socket 实现(二)

    本文将主要关注在Java中使用MINA来实现安全套接层(SSL)和传输层安全(TLS)协议,这两个协议是网络安全通信的基础,确保数据在网络中的加密传输。 首先,理解TLS/SSL的核心概念至关重要。它们都是为网络通信提供...

    SSLTLS 服务器瞬时 Diffie-Hellman 公共密钥过弱【原理扫描】 .txt

    【解决漏洞-亲测好用】SSLTLS 服务器瞬时 Diffie-Hellman 公共密钥过弱

    bcprov-ext-jdk15on-1.54.jar、bcprov-jdk15on-1.54.jar和ssl-provider-jvm16-0.2.jar

    "ssl-provider-jvm16-0.2.jar"是一个针对JVM 1.6的SSL(Secure Socket Layer)提供者。SSL是一种网络通信安全协议,主要用于确保数据在网络传输过程中的安全,通过使用公钥/私钥技术进行身份验证和数据加密。此提供...

    perl-IO-Socket-IP-0.39-6.module_el8.4.0+646+45e06e4a.noarch.rpm

    官方离线安装包,亲测可用。使用rpm -ivh [rpm完整包名] 进行安装

    安卓Java Web Socket简单使用

    在Android平台上,Java Web Socket是一种实现双向通信的协议,它允许服务器和客户端实时交换数据,非常适合需要实时更新的应用,如在线聊天、游戏、股票交易等。本教程将介绍如何在Android应用中简单使用Java ...

    Java TCP-IP Socket编程-卡尔弗特.pdf

    Java TCP/IP Socket编程是网络通信领域中的核心技术,尤其在Java编程中,Socket是实现客户端与服务器之间通信的基础。本资料“Java TCP-IP Socket编程-卡尔弗特.pdf”旨在深入探讨如何利用Java语言进行TCP/IP套接字...

    python-backports-ssl_match_hostname-3.5.0.1-1.el7.noarch.rpm

    官方离线安装包,测试可用。使用rpm -ivh [rpm完整包名] 进行安装

Global site tag (gtag.js) - Google Analytics