Autenticação customizada de WCF – Parte I

Olá pessoal,

Estava conversando com um cliente sobre como um serviço WCF pode autenticar de maneira customizada as chamadas que recebe, confrontando as informações de usuário e senha com os dados de uma tabela em um banco de dados.

O primeiro para é criar uma classe para autenticar as chamadas do serviço. Esta classe deve herdar de System.IdentityModel.Selectors.UserNamePasswordValidator, disponível no assembly System.IdentityModel, e implementar o método Validate, conforme abaixo:

    1:  public class CustomUsernamePasswordValidator : UserNamePasswordValidator
    2:    {
    3:      public override void Validate(string userName, string password)
    4:      {
    5:        if (userName == null || password == null)
    6:        {
    7:          throw new ArgumentNullException();
    8:        }
    9:   
   10:        if (!(userName == "administrator" && password == "P@ssw0rd"))
   11:        {
   12:          throw new FaultException("Unknown username or invalid password");
   13:        }
   14:      }
   15:    }

Notem que por uma questão de facilidade não estou utilizando um banco de dados para validar usuário e senha, mas sim comparando as informações recebidas contra constantes no meu código. Se a autenticação não ocorrer com sucesso emito uma mensagem de erro do tipo FaulException, que é o tipo de exceção possível de ser propagada pelo WCF (isso vale um post).

Em seguida é necessário configurar o serviço para utilizar esta customização para autenticação no arquivo de configurações:

    1:  <services>
    2:      <service behaviorConfiguration="WCFService.CalculatorServiceBehavior" ...>
    3:          ...
    4:      </service>
    5:  </services>
    6:  <behaviors>
    7:      <serviceBehaviors>
    8:          <behavior name="WCFService.CalculatorServiceBehavior">
    9:              <serviceMetadata httpGetEnabled="True"/>
   10:              <serviceDebug includeExceptionDetailInFaults="False" />
   11:              <serviceCredentials>
   12:                  <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="WCFCustomAuthentication.CustomUsernamePasswordValidator, WCFCustomAuthentication"/>
   13:              </serviceCredentials>
   14:          </behavior>
   15:      </serviceBehaviors>
   16:  </behaviors>

Agora é necessário configurar tanto o serviço quanto o cliente para autenticar as chamadas através de usuário e senha nos seus bindings:

    1:  <bindings>
    2:      <wsHttpBinding>
    3:          <binding name="wsHttpBindingWithMessageSecurity">
    4:              <security mode="Message">
    5:                  <message clientCredentialType="UserName"/>
    6:              </security>
    7:          </binding>
    8:      </wsHttpBinding>
    9:  </bindings>

Como as informações de usuário e senha passam de maneira aberta é necessário configurar a comunicação para ocorrer de maneira segura utilizando um certificado, mas isto é assunto para o post Autenticação customizada de WCF – Parte II.

Por último também é necessário que o cliente do serviço informe as credenciais na chamadas das operações, assunto do post Autenticação customizada de WCF – Parte III.

Posts da série: