WCF UserName authentication and fault contracts

Refresh

December 2018

Views

2.3k time

6

I have a WCF service configured to use custom UserName validation via the overriden Validate() method of the System.IdentityModel.Selectors.UserNamePasswordValidator class.

All methods of the contract have been decorated with the FaultContractAttribute to specify a custom SOAP fault as being returnable.

When throwing FaultException<T>, where T is the type specified in the FaultContractAttribute, everything behaves as expected and I get the custom fault in the response XML.

However, if I try and throw FaultException<T> in the overriden Validate() method of the username authentication class, I get a generic SOAP fault with the following reason:

"The creator of this fault did not specify a Reason."

However, if I change the code to throw the general SOAP fault as in:

throw new FaultException("Authentication failed.");

I will at least get "Authentication failed." in the reason element.

My questions are:

  • Why aren't the FaultException<T> exceptions treated the same if they're thrown in the Validate() as they are within the service implementation?
  • Is it possible to have exceptions thrown in the Validate() method conform to the FaultContractAttribute specified on the contract methods?

Any help greatly appreciated. My own guess is that the authentication comes before the message is associated with any method of the contract, and therefore, is not associated with the FaultContractAttribute, but any article confirming this and giving a workaround would be very useful.

Tali

2 answers

0

Проблема заключается в том, что код валидации работает вне контекста каких - либо конкретное OperationContract, поэтому нет FaultContractэтого место WCF для обработки. Поэтому короткий ответ нет, вы не можете получить исключения , из пользовательского валидатора в честь 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

Это немного раздражает, но я вокруг него, делая это:

SecurityTokenValidationException stve 
  = Новый SecurityTokenValidationException ( «Неверное имя пользователя или пароль»);
бросить новый FaultException <SecurityTokenValidationException> (stve, stve.Message);

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