【问题标题】:How to configure TidFTP with SSL?如何使用 SSL 配置 TidFTP?
【发布时间】:2018-05-28 13:49:59
【问题描述】:

我编写了一个小型 FTP 客户端来管理我的 bluehost.com 帐户上的文件。现在我已经迁移到一家新的托管公司,我的程序将连接,但仅此而已。

连接后,我尝试获取根文件的清单;程序挂了一会儿,最后产生“读取超时”。

经过研究,我得出结论(可能是错误的)这与 SSL(我可以通过我的新主机使用)有关。我在表单中添加了一个TIdSSLIOHandlerSocketOpenSSL 组件,将其分配给myFTP 并设置UseTLS = utUseExplicitTLS

现在,当我尝试连接时,我收到 10054 错误。我找不到任何关于如何配置此连接的示例。

代码如下:

unit ct_FTP_Test;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
  Vcl.Graphics, Vcl.Forms, Vcl.StdCtrls, Vcl.Controls, IdTCPConnection, IdTCPClient,
  IdExplicitTLSClientServerBase, IdFTP, IdBaseComponent, IdComponent, IdIOHandler,
  IdIOHandlerSocket, IdIOHandlerStack, IdSSL, IdSSLOpenSSL, IdAntiFreezeBase,
  IdFTPCommon, IdAntiFreeze;

type
  TForm1 = class(TForm)
    btnConnectFTP: TButton;
    Label2: TLabel;
    Label4: TLabel;
    mem: TMemo;
    btnShowFolder: TButton;
    idSSLIOHandlerSocketOpenSSL: TIdSSLIOHandlerSocketOpenSSL;
    myFTP: TIdFTP;
    edHost: TEdit;
    edUser: TEdit;
    edPassword: TEdit;
    Label1: TLabel;
    Label3: TLabel;
    Label5: TLabel;
    idAntiFreeze: TIdAntiFreeze;
    edPort: TEdit;
    Label6: TLabel;
    ckbUseSSL: TCheckBox;
    procedure btnConnectFTPClick(Sender: TObject);
    procedure btnShowFolderClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    procedure GetFolderInventory;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.GetFolderInventory;
var DirList : TStringList;
begin
  if (not myFTP.Connected) then
    begin
      Label2.Caption := 'You are not connected...';
      Exit;
    end;

  try
    try
      Label4.Caption := 'Going to root...';
      myFTP.ChangeDir('/');
      Label4.Caption := 'At root, getting DirList...';

      DirList := TStringList.Create;
      myFTP.List(DirList, '', True);

      Label2.Caption := '';
      Label4.Caption := IntToStr(DirList.Count) + ' files and folders found';

      mem.Lines.Assign(DirList);
    except on e:Exception do
      begin
        Label4.Caption := 'Unable to show contents';
        Label2.Caption := e.Message;
      end;
    end;
  finally
    FreeAndNil(DirList);
  end;
end;

procedure TForm1.btnShowFolderClick(Sender: TObject);
begin
  GetFolderInventory;
end;

procedure TForm1.btnConnectFTPClick(Sender: TObject);
begin
  try
    Label2.Caption := '';
    Label4.Caption := '';

    if (myFTP.Connected) then
      myFTP.Disconnect;

    if (edHost.Text = '') then
      begin
        edHost.SetFocus;
        Label4.Caption := 'Host required.';
        Exit;
      end;

    if (edUser.Text = '') then
      begin
        edUser.SetFocus;
        Label4.Caption := 'User required.';
        Exit;
      end;

    if (edPassword.Text = '') then
      begin
        edPassword.SetFocus;
        Label4.Caption := 'Password required.';
        Exit;
      end;

    if (edPort.Text = '') then
      begin
        edPort.SetFocus;
        Label4.Caption := 'Port required.';
        Exit;
      end;

    myFTP.Host := edHost.Text;
    myFTP.Username := edUser.Text;
    myFTP.Password := edPassword.Text;
    myFTP.Port := StrToInt(edPort.Text);

    if (ckbUseSSL.Checked) then
      begin
        myFTP.UseTLS := utUseExplicitTLS;
        myFTP.DataPortProtection := ftpdpsPrivate;
        myFTP.Passive := True;
      end
    else
      begin
        myFTP.DataPortProtection := ftpdpsClear;
        myFTP.UseTLS := utNoTLSSupport;
        myFTP.Passive := False;
      end;


    myFTP.Connect;
    Label4.Caption := 'Connected';
    Label2.Caption := '';
  except on e:Exception do
    begin
      Label4.Caption := 'Failed to connect';
      Label2.Caption := e.Message;
    end;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Label2.Caption := '';
  Label4.Caption := '';
end;

end.

这是 dfm:

object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 568
  ClientWidth = 704
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  OnCreate = FormCreate
  PixelsPerInch = 96
  TextHeight = 13
  object Label2: TLabel
    Left = 120
    Top = 101
    Width = 496
    Height = 44
    AutoSize = False
    Caption = '[...]'
    WordWrap = True
  end
  object Label4: TLabel
    Left = 120
    Top = 72
    Width = 20
    Height = 13
    Caption = '[...]'
  end
  object Label1: TLabel
    Left = 120
    Top = 37
    Width = 22
    Height = 13
    Caption = 'Host'
  end
  object Label3: TLabel
    Left = 272
    Top = 37
    Width = 22
    Height = 13
    Caption = 'User'
  end
  object Label5: TLabel
    Left = 456
    Top = 37
    Width = 32
    Height = 13
    Caption = 'PWord'
  end
  object Label6: TLabel
    Left = 605
    Top = 37
    Width = 20
    Height = 13
    Caption = 'Port'
  end
  object btnConnectFTP: TButton
    Left = 32
    Top = 32
    Width = 75
    Height = 25
    Caption = 'Connect'
    TabOrder = 0
    OnClick = btnConnectFTPClick
  end
  object mem: TMemo
    Left = 113
    Top = 160
    Width = 503
    Height = 377
    ScrollBars = ssVertical
    TabOrder = 1
    WordWrap = False
  end
  object btnShowFolder: TButton
    Left = 32
    Top = 160
    Width = 75
    Height = 25
    Caption = 'Show Folder'
    TabOrder = 2
    OnClick = btnShowFolderClick
  end
  object edHost: TEdit
    Left = 148
    Top = 32
    Width = 105
    Height = 21
    TabOrder = 3
  end
  object edUser: TEdit
    Left = 300
    Top = 32
    Width = 137
    Height = 21
    TabOrder = 4
  end
  object edPassword: TEdit
    Left = 495
    Top = 32
    Width = 90
    Height = 21
    TabOrder = 5
  end
  object edPort: TEdit
    Left = 633
    Top = 32
    Width = 40
    Height = 21
    NumbersOnly = True
    TabOrder = 6
    Text = '21'
  end
  object ckbUseSSL: TCheckBox
    Left = 40
    Top = 72
    Width = 57
    Height = 17
    Caption = 'Use SSL'
    TabOrder = 7
  end
  object idSSLIOHandlerSocketOpenSSL: TIdSSLIOHandlerSocketOpenSSL
    MaxLineAction = maException
    DefaultPort = 0
    ReadTimeout = 60000
    SSLOptions.Mode = sslmClient
    SSLOptions.VerifyMode = []
    SSLOptions.VerifyDepth = 0
    Left = 69
    Top = 318
  end
  object myFTP: TIdFTP
    IOHandler = idSSLIOHandlerSocketOpenSSL
    IPVersion = Id_IPv4
    ConnectTimeout = 0
    NATKeepAlive.UseKeepAlive = False
    NATKeepAlive.IdleTimeMS = 0
    NATKeepAlive.IntervalMS = 0
    ProxySettings.ProxyType = fpcmNone
    ProxySettings.Port = 0
    Left = 22
    Top = 278
  end
  object idAntiFreeze: TIdAntiFreeze
    Left = 24
    Top = 216
  end
end

任何帮助将不胜感激。

【问题讨论】:

  • 设置UseTLS 属性可能更改Port 属性,因此请确保您实际连接到您期望的正确端口。
  • 谢谢@RemyLebeau。我检查了端口,它仍然设置为 21(这是托管公司指定的)。仍然收到相同的 10054 错误。
  • 10054 是与远程对等方的异常断开连接。如果不了解更多有关您的设置的信息,并且可能不了解来回捕获原始套接字流量,就很难诊断出此类问题。哪一行代码失败了?您使用的是主动模式还是被动模式传输?您将DataPortProtection 属性设置为什么?
  • @RemyLebeau,我编辑了问题以添加我所在位置的完整来源。这段代码与我的旧主机的唯一区别在于这包括尝试使用 SSL(这可能是不必要的)。由于这曾经有效,我从来不需要处理调查“原始套接字流量”......我该去哪里得到它?谢谢!
  • 在命令端口上通过 UseTLS 启用 SSL 时,您没有将 TIdFTP.DataPortProtection 属性设置为 ftpdpsPrivate 以在传输端口上启用 SSL。此外,TIdFTP.Passive 属性默认为 False,这意味着 FTP 服务器连接到TIdFTP 以进行传输连接。尝试将 TIdFTP.Passive 设置为 True,以便 TIdFTP 改为连接到 FTP 服务器。

标签: delphi ftp delphi-xe2 indy indy10


【解决方案1】:

尝试通过设置TIdSSLIOHandlerSocketOpenSSL 的正确属性(不记得实际属性名称)来允许所有 SLL 方法/类型。

【讨论】:

  • 您正在考虑SSLOptions.MethodSSLOptions.SSLVersions 属性
  • @skippix:因为您要连接到其他主机,所以支持的 SSL 版本可能不同。因此,允许所有版本将确保这不是问题。
猜你喜欢
  • 2021-04-04
  • 2016-03-17
  • 1970-01-01
  • 2020-06-18
  • 2020-02-23
  • 2019-03-04
  • 1970-01-01
  • 2018-12-24
  • 2016-12-21
相关资源
最近更新 更多