UserName e Password em serviços WCF para Silverlight


Como sabemos, podemos utilizar usuário e senha para autenticar um usuário em um serviço WCF, mas há algumas regras que precisam ser seguidas, como eu já comentei neste post. Uma dessas regras é que não podemos trafegar essas informações sem alguma criptografia. Mesmo que o serviço seja exposto via HTTP, a utilização de um certificado (não do HTTPS), fará este papel.

Eu mostrei como customizar a autenticação neste artigo, e note que estou usando um certificado e o serviço não está disponível através do HTTPS. Além disso, o binding que está sendo utilizado é o WSHttpBinding, que sabe como efetuar a criptografia das informações. Agora imagine que este serviço pode ser consumido por uma aplicação Silverlight. Infelizmente o WCF do Silverlight não tem suporte ao WSHttpBinding, somente ao BasicHttpBinding, e mais recentemente, via NetTcpBinding.

Mas como podemos proceder neste caso? Para poder disponibilizar serviços WCF para uma aplicação Silverlight, precisaremos recorrer a segurança em nível de transporte, para garantir a proteção. Para isso, estamos obrigados à expor o serviço através de HTTPS, e as credenciais estarão protegidas dentro da mensagem. Mas antes da versão 3.0 do Silverlight, era díficil expor e/ou consumir serviços WCF que exigem usuário e senha, já que você precisava criar headers customizados para acomodar essas informações, assim como era (ou ainda é) feito pelos ASP.NET Web Services.

A partir da versão 3.0, o Microsoft introduziu mais uma opção no binding BasicHttpBinding (do Silverlight), que é a TransportWithMessageCredential. Com esta opção definida, o serviço deverá ser disponibilizado via HTTPS, e as credencias viajarão dentro da mensagem, sem precisarmos escrever qualquer código adicional. Felizmente, quando efetuamos a referência em uma aplicação Silverlight, o proxy gerado já disponibiliza a propriedade ClientCredentials, onde podemos atribuir o usuário e senha, que eventualmente vem de controles TextBoxes da tela.

A configuração do serviço é relativamente simples. O primeiro passo é criar o validador customizado de usuários, que nada mais é do que uma classe que herda de UserNamePasswordValidator, e dentro do método Validate, você escreve a regra para buscar e validar o usuário. Para maiores detalhes de como isso funciona, consulte este artigo. Depois note também que definimos a segurança como sendo TransportWithMessageCredential, conforme comentamos acima.

<system.serviceModel>
  <services>
    <service name=”ServicoDeClientes”
             behaviorConfiguration=”bhr”>
      <endpoint name=”srv”
                binding=”basicHttpBinding”
                contract=”IContrato”
                bindingConfiguration=”bc”/>
    </service>
  </services>
  <bindings>
    <basicHttpBinding>
      <binding name=”bc”>
        <security mode=”TransportWithMessageCredential”/>
      </binding>
    </basicHttpBinding>
  </bindings>
  <behaviors>
    <serviceBehaviors>
      <behavior name=”bhr”>
        <serviceMetadata httpsGetEnabled=”true”/>
        <serviceCredentials>
          <userNameAuthentication
            customUserNamePasswordValidatorType=”ValidadorDeUsuarios”
            userNamePasswordValidationMode=”Custom”/>
        </serviceCredentials>
      </behavior>
    </serviceBehaviors>
  </behaviors>
</system.serviceModel>

Depois da configuração do serviço, o publicamos e, consequentemente, referenciamos na aplicação cliente (Silverlight). Ao referenciá-lo, já podemos notar que o arquivo de configuração já está devidamente especificado com a mesma opção de segurança: TransportWithMessageCredential.

<configuration>
  <system.serviceModel>
    <client>
      <endpoint address=”https://localhost/SLTest/ServicoDeClientes.svc&#8221;
                binding=”basicHttpBinding”
                bindingConfiguration=”srv”
                contract=”ServicoDeClientes.IContrato”
                name=”srv” />
    </client>
    <bindings>
      <basicHttpBinding>
        <binding name=”srv”>
          <security mode=”TransportWithMessageCredential” />
        </binding>
      </basicHttpBinding>
    </bindings>
  </system.serviceModel>
</configuration>

Com isso, tudo o que nos resta é instanciar o proxy e definir a propriedade ClientCredentials, que receberá os credenciais do usuário. Depois de configurado, você já está apto a chamar qualquer operação exposta pelo serviço, que antes dela ser efetivamente executada, o runtime do WCF avaliará as credenciais informadas, se certfificando de que são válidas, e somente a partir daí, irá invocar o método.

ServicoDeClientes.ContratoClient p = new ServicoDeClientes.ContratoClient();
p.ClientCredentials.UserName.UserName = this.Login.Text;
p.ClientCredentials.UserName.Password = this.Password.Text;

p.PingCompleted += (s, args) => this.textBlock1.Text = args.Result;
p.PingAsync();

A chamada da operação de forma assíncrona, nada tem nada a ver com a questão de segurança. Isso é apenas uma característica do WCF do Silverlight, e mesmo que não houvesse qualquer nível de segurança envolvido, a forma para invocar uma operação seria a mesma.

Anúncios

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s