關於Ftp使用SSL流程認證
本文章使用的是C#,ftp服務器為FileZilla
注:如果不是使用的Socket可以使用FtpWebRequst類,說實話,該類比較簡單,但現在說的是SOCKET,網上關於這方面的實在太少了
流程(不會畫圖,就筆述)
大致流程:
一.ssl的認證
1.連接到指定的ftp服務器(當前還未登陸)
2.發送"AUTH SSL"或"AUTH TLS"命令,返回234則成功
3.使用剛才連接的socket創建SSLSTream對象
創建對象示例如下
Socket mClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPEndPoint mEPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 21); mClientSocket.Connect(mEPoint); //發送ssl命令 SendCommand("AUTH SSL"); NetworkStream network = new NetworkStream(mClientSocket); SslStream sslStream = new SslStream(network, true, (o,i,s,j)=>true, null);
//ssl驗證 sslStream.AuthenticateAsClient("certName", null, System.Security.Authentication.SslProtocols.Ssl3 | System.Security.Authentication.SslProtocols.Tls, true);
4.成功驗證后發送USER,PASS等命令(此時發送命令以及接收返回值都應當使用第三步創建的"sslStream"對象,所以需要有一個全局變量來保存該對象)
5.發送"PBSZ 0"命令,發送"PROT P"命令,登陸完成
6.以讀取目錄中文件為例
6.1 在獲取到端口並創建了DataSocket后,發送"LIST"命令之后,應當以DataSocket創建一個SslStream對象出來,並且進行ssl驗證
6.2 使用第3步的的SslStream對象獲取一下返回值(否則后面獲取文件列表會有問題)
6.3 在6.2完成后使用6.1的SslStream對象獲取返回值,即是當前目錄的所有文件/目錄列表
注意:
1.socket ssl認證需要兩個sslStream對象,一個是連接的sslStream對象,該對象在創建並驗證成功后主要用來向ftp服務器發送命令,在未創建數據的sslStream對象時獲取服務器返回信息也使用該對象
2.另一個為數據對象,當創建了一個傳輸端口的Socket並創建其sslStream對象並驗證后,后續的向ftp發送命令,以及獲取返回值均使用的該對象
3.關於如何使用傳輸socket的sslstream來獲取返回值
這一步也是困擾我很久的,因為sslStream沒有方法可以知道當前流中還剩下多少數據,使用ReadByte方法會阻塞線程
所以我把傳輸的DataSocket給保存到全局變量中,使用DataSocket可以知道剩下的數據量
示例方法如下:
/// <summary> /// 獲取服務器返回信息 /// </summary> /// <param name="byteSize">緩沖區大小</param> /// <returns></returns> public List<byte> Receive(int byteSize) { byte[] buffer = new byte[byteSize]; string result = string.Empty; List<byte> list = new List<byte>(); do { //使用傳輸的sslStream來獲取返回信息 int byts = DataSSLStream.Read(buffer, 0, buffer.Length); list.AddRange(buffer.Take(byts)); //查看當前的傳輸socket中是否還有數據 if (DataSocket.Available == 0) { break; } } while (true); return list; }
==============后面代碼有時間再上