WCF UserName аутентификация и ошибки договоров - PullRequest
6 голосов
/ 24 августа 2009

У меня есть служба WCF, настроенная на использование пользовательской проверки UserName через переопределенный метод Validate () класса System.IdentityModel.Selectors.UserNamePasswordValidator.

Все методы контракта были украшены атрибутом FaultContractAttribute, чтобы указать, что настраиваемая ошибка SOAP является возвращаемой.

При выдаче FaultException , где T - это тип, указанный в FaultContractAttribute, все ведет себя как ожидалось, и я получаю пользовательскую ошибку в XML-ответе.

Однако, если я попытаюсь сгенерировать FaultException в переопределенном методе Validate () класса аутентификации имени пользователя, я получу общую ошибку SOAP по следующей причине:

«Создатель этой ошибки не указал причину.»

Однако, если я изменю код для генерации общей ошибки SOAP, как в:

throw new FaultException("Authentication failed.");

По крайней мере, я получу "Ошибка аутентификации". в элементе разума.

Мои вопросы:

  • Почему исключения FaultException не обрабатываются одинаково, если они выбрасываются в Validate (), как в реализации службы?
  • Возможно ли, чтобы исключения, генерируемые в методе Validate (), соответствовали атрибуту FaultContractAttribute, указанному в методах контракта?

Любая помощь с благодарностью. Я предполагаю, что аутентификация происходит до того, как сообщение будет связано с каким-либо методом контракта, и, следовательно, не связано с FaultContractAttribute, но любая статья, подтверждающая это и предлагающая обходной путь, будет очень полезной.

Тали

Ответы [ 2 ]

0 голосов
/ 20 апреля 2012

Проблема в том, что пользовательский код проверки выполняется вне контекста какого-либо конкретного OperationContract, поэтому для WCF нет места для обработки FaultContract. Таким образом, короткий ответ - нет, вы не можете получить исключения, выданные вашим пользовательским валидатором, чтобы соблюдать FaultContract.

У вас есть несколько вариантов здесь. Один, который я предпочитаю, это бросить неуниверсальный FaultException и предоставить заранее определенный FaultCode; таким образом, мои блоки улавливания могут отличать недостатки контракта от ошибок "трубопровода". Обратите внимание, что любое исключение, которое вы выбрасываете из пользовательского валидатора, должно возвращаться как MessageSecurityException, как показано ниже:

// Custom Validator:
public override void Validate(string userName, string password)
{
  throw new FaultException(
    "Invalid username or password.", 
    new FaultCode("AUTHENTICATION_FAILURE"));
}

// Client Code:
try
{
  client.DoSomething();
}
catch ( MessageSecurityException ex )
{
  var inner = ex.InnerException as FaultException;
  if (inner != null && inner.Code.Name.Equals("AUTHENTICATION_FAILURE"))
  { 
    // Security failure.
  }
}
catch ( FaultException<SomethingFault> ex )
{
  // Exception from the method itself.
}
0 голосов
/ 25 августа 2010

Это немного раздражает, но я справился с этим, сделав следующее:

SecurityTokenValidationException stve 
  = new SecurityTokenValidationException("Invalid username or password");
throw new FaultException<SecurityTokenValidationException>(stve, stve.Message);

Включение сообщения дополнительно означает, что вы не получите глупое сообщение "не указана причина".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...