Перейти к содержанию
Fire Monkey от А до Я
  • 0

THTTPClient и просроченный сертификат сервера


Евгений Корепов

Вопрос

Есть сайт просроченным сертификатом безопасности (госконтора, такое у них в порядке вещей), сертификат могут обновить завтра, а могут и через год, но работать с ним надо.

Var HTTPClient: THTTPClient;
    HTTPResponse: IHTTPResponse;
begin
  HTTPClient:=THTTPClient.Create;
  HTTPClient.OnValidateServerCertificate:=HTTPClientValidateServerCertificate;
.....
  try
  	HTTPResponse:=HTTPClient.Post(FHTTPRec.Query,FHTTPRec.PostData);
  except
	on E : Exception do
    begin
      FHTTPRec.ErrorCode:=-1;
      FHTTPRec.ErrorMsg:=E.Message;
    end;
.....
end;

procedure THTTPThread.HTTPClientValidateServerCertificate(const Sender: TObject;
  const ARequest: TURLRequest; const Certificate: TCertificate;
  var Accepted: Boolean);
begin
  Accepted:=True;
end;

Под Windows код работает идеально - вызывается HTTPClientValidateServerCertificate, где принудительно доверяем сертификату.

Под Андроид HTTPClientValidateServerCertificate или игнорируется, или до процедуры не доходит. Получаю ошибку:

First chance exception at $A06ECCE5. Exception class EJNIException with message 'java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.'. Process tratata.apk (25487)
First chance exception at $A0EA44F5. Exception class ENetHTTPCertificateException with message 'Server Certificate Invalid or not present'. Process tratata.apk (25487)

Как победить проблему? 

P.S. До этого проект работал на Indy, там подобные проблемы успешно игнорировались. Но решил перевести все на THTTPClient и вот результат :-(

 

Ссылка на комментарий

Рекомендуемые сообщения

  • 0
37 минут назад, Rusland сказал:

Я использую такой же код и на Андройде Accepted:=True;  и у меня прокатывает. Что за сайт?

Вот https://cabinet.komiesc.ru/cabinet 

Ссылка на комментарий
  • 0

Евгений Корепов, проверил - работает на Android

procedure TForm1.OnAuthEvent(const Sender: TObject;
  AnAuthTarget: TAuthTargetType; const ARealm, AURL: string; var AUserName,
  APassword: string; var AbortAuth: Boolean;
  var Persistence: TAuthPersistenceType);
var
  MyCredential: TCredentialsStorage.TCredential;
begin
  MyCredential := TNetHTTPClient(Sender).CredentialsStorage.FindAccurateCredential(AnAuthTarget, '');
  AUserName := MyCredential.UserName;
  APassword := MyCredential.Password;
end;

procedure TForm1.OnValidateServerCertificate(
  const Sender: TObject; const ARequest: TURLRequest;
  const Certificate: TCertificate; var Accepted: Boolean);
begin
  Accepted:=true;
end;

 

Изменено пользователем Rusland
Ссылка на комментарий
  • 0

Вопрос решился по другому - доступ по http тоже работает, никакого принудительного перевода на https. На ФЗ "О персональных данных" видимо плевать с большой колокольни...

Ссылка на комментарий
  • 0
16 минут назад, Евгений Корепов сказал:

Вопрос решился по другому - доступ по http тоже работает, никакого принудительного перевода на https. На ФЗ "О персональных данных" видимо плевать с большой колокольни...

Скорее всего горе-программисты;))

Ссылка на комментарий
  • 0

Прикрепил тестовый проект на котором воспроизводится ошибка. Код дублирую для наглядности:

unit UnitFormMain;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.ScrollBox,
  FMX.Memo, FMX.Controls.Presentation, FMX.StdCtrls,
  System.Net.HTTPClient,
  System.Net.Mime,
  System.Net.URLClient;

type
  TFormMain = class(TForm)
    ButtonPost: TButton;
    Memo: TMemo;
    procedure FormCreate(Sender: TObject);
    procedure ButtonPostClick(Sender: TObject);
  private
    { Private declarations }
    FHTTPClient: THTTPClient;
    FMultipartFormData : TMultipartFormData;
    HTTPResponse: IHTTPResponse;
    procedure HTTPClientValidateServerCertificate(const Sender: TObject;
      const ARequest: TURLRequest; const Certificate: TCertificate;
      var Accepted: Boolean);
  public
    { Public declarations }
  end;

var
  FormMain: TFormMain;

implementation

{$R *.fmx}

procedure TFormMain.FormCreate(Sender: TObject);
begin
  FHTTPClient:=THTTPClient.Create;
  FHTTPClient.HandleRedirects:=False;
  FHTTPClient.AllowCookies:=True;
  FHTTPClient.MaxRedirects:=3;
  FHTTPClient.Accept:='text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8';
  FHTTPClient.AcceptEncoding:='gzip, deflate';
  FHTTPClient.AcceptLanguage:='ru,en-US;q=0.8,en;q=0.6';
  FHTTPClient.ContentType:='application/x-www-form-urlencoded';
  FHTTPClient.UserAgent:='Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.81 Safari/537.36';
  FHTTPClient.OnValidateServerCertificate:=HTTPClientValidateServerCertificate;

  FMultipartFormData:=TMultipartFormData.Create;
  FMultipartFormData.AddField('action','login');
  FMultipartFormData.AddField('id_domain', '21');
  FMultipartFormData.AddField('login', '102355555');
  FMultipartFormData.AddField('password', 'n7icyq34783q');
end;

procedure TFormMain.ButtonPostClick(Sender: TObject);
Var ALocation : String;
begin
  try
    HTTPResponse:=FHTTPClient.Post('https://cabinet.komiesc.ru/cabinet',FMultipartFormData);
  except
    on E : Exception do
    begin
      if Not (E.Message.Contains('302') or E.Message.Contains('403')) then
      begin
        Memo.Lines.Add(E.Message);
        Exit;
      end;
    end;
  end;
// Код ниже можно игнорировать, это обработка редиректов при удачной авторизации
  if Assigned(HTTPResponse) then
  begin
    if HTTPResponse.StatusCode=302 then
    begin
      HTTPResponse.Headers;
      HTTPResponse.Date;
      FreeAndNil(FMultipartFormData);
      FMultipartFormData:=TMultipartFormData.Create;
      ALocation:=HTTPResponse.HeaderValue['Location'];
      ALocation:='https://cabinet.komiesc.ru/input_controlchecks';
      ALocation:='http://cabinet.komiesc.ru/input_controlchecks';
      if Not ALocation.IsEmpty then
      begin
        HTTPResponse:=FHTTPClient.Post('https://cabinet.komiesc.ru/input_controlchecks', FMultipartFormData);
        Memo.Lines.Text:=HTTPResponse.ContentAsString;
      end;
    end;
  end;
end;

procedure TFormMain.HTTPClientValidateServerCertificate(const Sender: TObject;
  const ARequest: TURLRequest; const Certificate: TCertificate;
  var Accepted: Boolean);
begin
  Accepted:=True;
end;

end.

 

test061 https.7z

Ссылка на комментарий

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...