Клиентский код Delphi Datasnap не получает неавторизованное исключение

Я использую Delphi 10.1 Berlin Update 2 Enterprise и клиент-серверную структуру REST DataSnap.

Если я запускаю приложение без отладки и вызываю метод, который пользователь не имеет права вызывать, код выполняется без каких-либо исключений, и метод возвращает нулевой ответ.

При интерактивной отладке вызова клиентского метода сервера DataSnap, я получаю два всплывающих исключения, касающихся «неавторизованного».

Первый пузырится и заменяется вторым.

Второе исключение «съедается», и сеанс / соединение просто закрывается, а затем метод возвращает пустой результат (например, ноль, если тип возвращаемого значения является целым числом, и пустую строку для типа возвращаемого значения строки).

Это происходит в следующем разделе кода ближе к концу метода ExecuteRequest в модуле Datasnap.DSClientRest:

except
  on E: TDSRestProtocolException do
    LSessionExpired;
end;

Почему эти исключения (например, TDSRestProtocolException) не доходят до моего кода?

Я думаю, что это новость для обновления 2, и я помню, как эти исключения всплывали в моем коде до обновления 2.

Attached - это скелетный пример (стандартный пример, созданный мастерами Delphi), который демонстрирует проблему - нажмите кнопку, и вы получите «» вместо «4321», потому что пользователь не авторизован, но нет исключения времени выполнения.

Я новичок в DataSnap, так что несите меня :-)

Заранее спасибо за полезные ответы =)


person Boris Bosnjak    schedule 30.01.2017    source источник
comment
ПРИМЕЧАНИЕ: здесь используется модуль REST Client DataSnap (http), а не простой модуль TCP / IP Client DataSnap.   -  person Boris Bosnjak    schedule 30.01.2017


Ответы (3)


Это происходит из-за того, что компонент DSAuthenticationManager1 добавлен в веб-модуль сервера, а на стороне клиента не удается пройти аутентификацию.

Просмотрите это, чтобы узнать, как работать с аутентификацией. Добавление аутентификации и авторизации

person pn098    schedule 30.01.2017
comment
В статье используется клиентский модуль DataSnap, а не клиентский REST-модуль DataSnap, который мне нужно использовать. Даже если я установлю имя пользователя в клиентском компоненте DSRestConnection1, исключение авторизации все равно не достигнет пользовательского интерфейса. ПРИМЕЧАНИЕ! Эти исключения встречаются в коде библиотеки, но не дошли до моего кода. Проверка авторизации выполняется, но мой код пользовательского интерфейса не видит исключения, потому что они съедаются в коде библиотеки. - person Boris Bosnjak; 30.01.2017
comment
Для ясности, SQLConnection1 в статье Добавление аутентификации и авторизации работает должным образом, а пользовательский интерфейс видит несанкционированное исключение. Это DSRestConnection1 в моем примере проекта, который не видит того же исключения в той же конфигурации. - person Boris Bosnjak; 30.01.2017

Ну .. Я не уверен, но попробуйте предоставить имя пользователя и пароль для компонента DSRestConnection1 до того, как будет создан экземпляр серверных методов

procedure TClientModule1.TestCon(aUsername, aPassword: string);
var
lServerMethodsClient : TServerMethodsClient;
begin
DSRestConnection1.UserName := aUsername;
DSRestConnection1.Password := aPassword;
lServerMethodsClient:=TServerMethodsClient.Create(DSRestConnection1);
end;

и попробуйте вызвать эту функцию из своей клиентской формы

procedure TF_ClientForm.Button1Click(Sender: TObject);
begin
ClientModule1.TestCon(EdtUsername.Text, EdtPassword.Text);
end;
person pn098    schedule 31.01.2017
comment
Проблема не в авторизации, а в авторизации :-) - person Boris Bosnjak; 03.02.2017
comment
В итоге я переключился на сервер DataSnap и клиентский модуль DataSnap через TCP / IP. Красиво работает. Обратите внимание, почему эквиваленты REST имеют эту проблему, но я потратил достаточно времени! Спасибо, pn098, что нашли время внести свой вклад = D - person Boris Bosnjak; 05.02.2017

Возможно, немного поздно, но сегодня утром я глубоко погрузился в это, потому что после обновления с Delphi XE6 до Tokyo 10.2 приложения, в которых я использовал компонент TDSRestConnection, сломались. Хотя я указал правильное имя пользователя и пароль, они не появились в событии TDSAuthenticationManager.OnUserAuthenticate. «Проблема» связана с новой реализацией System.Net.HttpClient.

Короче говоря (или немного короче): клиентский компонент не отправляет учетные данные, пока принимающий сервер не потребует их, отправив ответ 401. После получения этого (правильно отформатированного) ответа клиент снова просматривает учетные данные de TDSConnection. На стороне клиента поддерживается полный список URL-адресов с требованиями к учетным данным, поэтому повторяющиеся вызовы одного и того же URL-адреса выполняются более плавно.

Я добавил этот код в WebModule сервера (где находится TDSRESTWebDispatcher), который решил мои проблемы:

procedure TwbmMain.WebModuleBeforeDispatch(Sender: TObject; Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
var
  LAuthorization: string;
begin
  inherited;

  if Request.PathInfo.StartsWith('/datasnap/') then
  begin
    LAuthorization := TNetEncoding.Base64.Decode(Request.Authorization.Replace('Basic ', ''));

    if LAuthorization.IsEmpty then
    begin
      Response.StatusCode := 401;
      Response.WWWAuthenticate := 'Basic';
      Handled := True;
    end;
  end;
end;

Поскольку мои приложения предоставляют некоторые загружаемые элементы, такие как логотип и т. Д., Я ограничил проверку только теми URL-адресами, которые имеют какое-либо отношение к привязке данных.

Надеюсь, это будет полезно другим!

person Frans van Meir    schedule 22.12.2018