Delphi XE5 TRESTRequest获取ssl3_read_bytes:sslv3警报握手失败

时间:2019-05-30 04:18:02

标签: rest ssl indy delphi-xe5

我遇到错误

  

REST请求失败!使用SSL连接时出错。错误:14094410:SSL   例程:ssl3_read_bytes:sslv3警报握手失败

使用TREST组件,这是示例代码-以下是完整的单元代码
似乎是特定于网址链接的,例如其他https:通话效果很好

function Getcall_UsingRest : String;
var
  fRstclnt1: TRESTClient;
  fRstrqst1: TRESTRequest;
  fRstrspns1: TRESTResponse;
begin
  result := '';
  try
    fRstclnt1:= TRESTClient.Create('https://au-api.basiq.io');
    fRstrqst1:= TRESTRequest.Create(nil);
    fRstrspns1:= TRESTResponse.Create(nil);
    try
      fRstrqst1.Client := fRstclnt1;
      fRstrqst1.Response := fRstrspns1;

      fRstrqst1.Execute;
      result := fRstrspns1.Content;
    finally
      fRstclnt1.Free;
      fRstrqst1.Free;
      fRstrspns1.Free;
    end;
  except
    on E:Exception do begin
      result := e.Message;
    end;
  end;
end;

我一直在尝试以下方法进行修复,但是我无法使其正常工作

使用TIdHTTP组件我遇到相同的错误

function Getcall_UsingHTTP_WithSameIssue : String;
var
  fIdHTTP1: TIdHTTP;
  fIdSSLIOHandlerSocketOpenSSL1: TIdSSLIOHandlerSocketOpenSSL;
  fresp: TMemoryStream;
  fMySL : TStringList;
begin
  result := '';
  try
    fIdHTTP1:= TIdHTTP.Create(nil);
    try
      fIdSSLIOHandlerSocketOpenSSL1 := TIdSSLIOHandlerSocketOpenSSL.Create(fIdHTTP1);
      fIdHTTP1.IOHandler := fIdSSLIOHandlerSocketOpenSSL1;

      fresp := TMemoryStream.Create;
      fMySL := TStringList.Create;
      try
        fIdHTTP1.Get('https://au-api.basiq.io', fresp);
        fresp.Position := 0;
        fMySL.LoadFromStream( fresp );
        result := fMySL.Text;
      finally
        fMySL.Free;
        fresp.Free;
      end;
    finally
      fIdHTTP1.Free;
    end;
  except
    on E:Exception do begin
      result := e.Message;
    end;
  end;
end;

有一个针对此问题的解决方法

procedure OnStatusInfoEx(ASender: TObject; const AsslSocket: PSSL;
  const AWhere, Aret: TIdC_INT; const AType, AMsg: String);
begin
  SSL_set_tlsext_host_name(AsslSocket, Request.Host);
end;

在fIdSSLIOHandlerSocketOpenSSL1.OnStatusInfoEx上:= OnStatusInfoEx;

TIdSSLIOHandlerSocketOpenSSL组件埋在TRESTClient的深处,我一直无法找到一种方法来查看是否可以将上面的修复程序应用于TRESTClient

有人可以提供有关如何使TREST进行交流的帮助


这是上面示例的完整源代码

unit RestExample;

interface
uses
  System.Generics.Collections
, REST.Types
, REST.Client
, sysutils
, IdHTTP
, IdSSLOpenSSL
, IdSSLOpenSSLHeaders, IdCTypes
, system.Classes
;

function Getcall_UsingRest : String;
function Getcall_UsingHTTP_WithSameIssue : String;
function Getcall_UsingHTTP_WithFix : String;

type
  TCustomIdHTTP = class(TIdHTTP)
  public
    constructor Create(AOwner: TComponent);
  private
    procedure OnStatusInfoEx(ASender: TObject; const AsslSocket: PSSL; const AWhere, Aret: TIdC_INT; const AType, AMsg: String);
  end;

implementation


function Getcall_UsingRest : String;
var
  fRstclnt1: TRESTClient;
  fRstrqst1: TRESTRequest;
  fRstrspns1: TRESTResponse;
begin
  result := '';
  try
    fRstclnt1:= TRESTClient.Create('https://au-api.basiq.io');
    fRstrqst1:= TRESTRequest.Create(nil);
    fRstrspns1:= TRESTResponse.Create(nil);
    try
      fRstrqst1.Client := fRstclnt1;
      fRstrqst1.Response := fRstrspns1;

      fRstrqst1.Execute;
      result := fRstrspns1.Content;
    finally
      fRstclnt1.Free;
      fRstrqst1.Free;
      fRstrspns1.Free;
    end;
  except
    on E:Exception do begin
      result := e.Message;
    end;
  end;
end;

function Getcall_UsingHTTP_WithSameIssue : String;
var
  fIdHTTP1: TIdHTTP;
  fIdSSLIOHandlerSocketOpenSSL1: TIdSSLIOHandlerSocketOpenSSL;
  fresp: TMemoryStream;
  fMySL : TStringList;
begin
  result := '';
  try
    fIdHTTP1:= TIdHTTP.Create(nil);
    try
      fIdSSLIOHandlerSocketOpenSSL1 := TIdSSLIOHandlerSocketOpenSSL.Create(fIdHTTP1);
      fIdHTTP1.IOHandler := fIdSSLIOHandlerSocketOpenSSL1;

      fresp := TMemoryStream.Create;
      fMySL := TStringList.Create;
      try
        fIdHTTP1.Get('https://au-api.basiq.io', fresp);
        fresp.Position := 0;
        fMySL.LoadFromStream( fresp );
        result := fMySL.Text;
      finally
        fMySL.Free;
        fresp.Free;
      end;
    finally
      fIdHTTP1.Free;
    end;
  except
    on E:Exception do begin
      result := e.Message;
    end;
  end;
end;

function Getcall_UsingHTTP_WithFix : String;
var
  fTCustomIdHTTP: TCustomIdHTTP;
  fresp: TMemoryStream;
  fMySL : TStringList;
begin
  result := '';
  try
    fTCustomIdHTTP:= TCustomIdHTTP.Create(nil);
    try
      fresp := TMemoryStream.Create;
      fMySL := TStringList.Create;
      try
        fTCustomIdHTTP.Get('https://au-api.basiq.io', fresp);
        fresp.Position := 0;
        fMySL.LoadFromStream( fresp );
        result := fMySL.Text;
      finally
        fMySL.Free;
        fresp.Free;
      end;
    finally
      fTCustomIdHTTP.Free;
    end;
  except
    on E:Exception do begin
      result := e.Message;
    end;
  end;

end;

{ TCustomIdHTTP }

constructor TCustomIdHTTP.Create(AOwner: TComponent);
begin
  IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
  with IOHandler as TIdSSLIOHandlerSocketOpenSSL do begin
    OnStatusInfoEx := Self.OnStatusInfoEx;
  end;
  inherited Create(AOwner);
end;

procedure TCustomIdHTTP.OnStatusInfoEx(ASender: TObject; const AsslSocket: PSSL;
  const AWhere, Aret: TIdC_INT; const AType, AMsg: String);
begin
  SSL_set_tlsext_host_name(AsslSocket, Request.Host);
end;

end.

0 个答案:

没有答案