none
WCF - Usando autenticação em WsHttpbinding RRS feed

  • Pergunta

  • Fiz uma WCF Library, que consigo consumir normalmente por outra aplicação. Implementei a UserNamePasswordValidator. mas quando tento consumir o serviço, passando o user e pass, ao tentar acessar qualquer método do serviço, ele lança uma exception com a seguinte descrição:

    SOAP security negotiation with 'http://localhost:6000/FleuryServico/UserName' for target 'http://localhost:6000/Servico/UserName' failed. See inner exception for more details.

    Alguem sabe me dizer o que pode ser? Já tentei de tudo, e não funciona com essa forma de autenticação.

    Obrigado


    quarta-feira, 16 de setembro de 2009 18:54

Respostas

  • Boas Savoia,

    Não lembro a configuração padrão do WCF, mas tente especificar o tipo de validação do certificado na aplicação cliente, como mostrado abaixo:

        <behaviors>
          <endpointBehaviors>
            <behavior name="ClientBehavior">
              <clientCredentials>
                <serviceCertificate>
                  <authentication certificateValidationMode="PeerTrust" />
                </serviceCertificate>
              </clientCredentials>
            </behavior>
          </endpointBehaviors>
        </behaviors>

    Depois, vincule este behavior ao endpoint (ainda do lado do cliente):

            <client>
                <endpoint address="http://localhost:6000/ClienteServico/UserName"
                    binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IServicoIntegracao"
                    contract="ServiceReference1.IServicoIntegracao" name="WSHttpBinding_IServicoIntegracao"
                    behaviorConfiguration="ClientBehavior">
                    <identity>
                        <dns value="localhost" />
                    </identity>
                </endpoint>
            </client>


    http://www.israelaece.com
    • Marcado como Resposta Andre SBC quarta-feira, 16 de setembro de 2009 20:46
    quarta-feira, 16 de setembro de 2009 19:41
    Moderador

Todas as Respostas

  • Boas Savoia,

    Já tentou ver a exceção interna para ver o que ele mostra? Atente-se também para o uso do certificado.

    Este artigo pode te ajudar em algo, pois tem um passo a passo: http://www.israelaece.com/post/WCF-Seguranca-Autenticacao-e-Autorizacao-Customizadas.aspx
    http://www.israelaece.com
    quarta-feira, 16 de setembro de 2009 18:58
    Moderador
  • Então Israel, inclusive consultei esse seu arquivo.. estou fazendo o básico por enquanto... só para autenticar, sem testar as roles do usuário... veja os configs..

    server:

    <configuration>
      <system.web>
        <compilation debug="true" />
      </system.web>
     
     <appSettings>
      <add key="SimularServico" value="false"/>
     </appSettings>
     
      <!-- When deploying the service library project, the content of the config file must be added to the host's
      app.config file. System.Configuration does not support config files for libraries. -->
      <system.serviceModel>
        <diagnostics>
          <messageLogging logEntireMessage="true" logMalformedMessages="true"
            logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="true" />
        </diagnostics>
        <bindings>
          <wsHttpBinding>
            <binding name="NewBinding0">
              <security mode="Message">
                <message clientCredentialType="UserName" />
              </security>
            </binding>
          </wsHttpBinding>
        </bindings>
        <services>
          <service behaviorConfiguration="Empresa.Cliente.WebService.Service1Behavior"
            name="Empresa.Cliente.WebService.ServicoIntegracao">
            <endpoint address="UserName" binding="wsHttpBinding" bindingConfiguration="NewBinding0"
              contract="Empresa.Cliente.WebService.IServicoIntegracao">
              <identity>
                <dns value="localhost" />
              </identity>
            </endpoint>
            <host>
              <baseAddresses>
                <add baseAddress="http://localhost:6000/ClienteServico" />
              </baseAddresses>
            </host>
          </service>
        </services>
        <behaviors>
          <serviceBehaviors>
            <behavior name="Empresa.Cliente.WebService.Service1Behavior">
              <serviceMetadata httpGetEnabled="True"/>
              <serviceDebug includeExceptionDetailInFaults="False" />
       <serviceCredentials>
        <!--
        The serviceCredentials behavior allows one to specify a custom validator for username/password combinations.     
        -->
        <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="Empresa.Cliente.WebService.Autenticacao, Empresa.Cliente.WebService" />
         <!--
        The serviceCredentials behavior allows one to define a service certificate.
        A service certificate is used by a client to authenticate the service and provide message protection.
        This configuration references the "localhost" certificate installed during the setup instructions.
        -->
        <serviceCertificate findValue="localhost" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" />
       </serviceCredentials>
      </behavior>
          </serviceBehaviors>
        </behaviors>
      </system.serviceModel>
    </configuration>


    Cliente:

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
        <system.serviceModel>
            <bindings>
                <wsHttpBinding>
                    <binding name="WSHttpBinding_IServicoIntegracao" closeTimeout="00:01:00"
                        openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
                        bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
                        maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
                        messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
                        allowCookies="false">
                        <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                            maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                        <reliableSession ordered="true" inactivityTimeout="00:10:00"
                            enabled="false" />
                        <security mode="Message">
                            <transport clientCredentialType="Windows" proxyCredentialType="None"
                                realm="" />
                            <message clientCredentialType="UserName" negotiateServiceCredential="true"
                                algorithmSuite="Default" establishSecurityContext="true" />
                        </security>
                    </binding>
                </wsHttpBinding>
            </bindings>
            <client>
                <endpoint address="http://localhost:6000/ClienteServico/UserName"
                    binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IServicoIntegracao"
                    contract="ServiceReference1.IServicoIntegracao" name="WSHttpBinding_IServicoIntegracao">
                    <identity>
                        <dns value="localhost" />
                    </identity>
                </endpoint>
            </client>
        </system.serviceModel>
    </configuration>

    Rodei o certmgr para criar o certificado.... (isso vem no Samples da Microsoft)antes disso ele sempre me retornar um outro erro..

    echo off
    set SERVER_NAME=localhost
    echo ---------------------------------------------------------------------
    echo cleaning up the certificates from previous run
    certmgr.exe -del -r CurrentUser -s TrustedPeople -c -n %SERVER_NAME%
    certmgr.exe -del -r LocalMachine -s My -c -n %SERVER_NAME%

    echo ---------------------------------------------------------------------
    echo Server cert setup starting
    echo for server: %SERVER_NAME%
    echo making server cert
    makecert.exe -sr LocalMachine -ss MY -a sha1 -n CN=%SERVER_NAME% -sky exchange -pe
    echo copying server cert to client's CurrentUser store
    certmgr.exe -add -r LocalMachine -s My -c -n %SERVER_NAME% -r CurrentUser -s TrustedPeople
    echo ---------------------------------------------------------------------

    Código Client:

    ServiceReference1.ServicoIntegracaoClient servico = new ServiceReference1.ServicoIntegracaoClient();
    servico.ClientCredentials.UserName.UserName =
    "teste";
    servico.ClientCredentials.UserName.Password =
    "teste";

    servico.TestarServico();

    Isso está direto na library, usando o Test Client.. criei uma camada de Host, e mesmo assim tb não rolou.... tem idéia do que possa ser?


    o que vc quis dizer com exceção interna?  Debugando, ele nem chega a bater na Autenticacao.cs.

    Obrigado

    Savoia

     

    quarta-feira, 16 de setembro de 2009 19:20
  • Boas Savoia,

    Não lembro a configuração padrão do WCF, mas tente especificar o tipo de validação do certificado na aplicação cliente, como mostrado abaixo:

        <behaviors>
          <endpointBehaviors>
            <behavior name="ClientBehavior">
              <clientCredentials>
                <serviceCertificate>
                  <authentication certificateValidationMode="PeerTrust" />
                </serviceCertificate>
              </clientCredentials>
            </behavior>
          </endpointBehaviors>
        </behaviors>

    Depois, vincule este behavior ao endpoint (ainda do lado do cliente):

            <client>
                <endpoint address="http://localhost:6000/ClienteServico/UserName"
                    binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IServicoIntegracao"
                    contract="ServiceReference1.IServicoIntegracao" name="WSHttpBinding_IServicoIntegracao"
                    behaviorConfiguration="ClientBehavior">
                    <identity>
                        <dns value="localhost" />
                    </identity>
                </endpoint>
            </client>


    http://www.israelaece.com
    • Marcado como Resposta Andre SBC quarta-feira, 16 de setembro de 2009 20:46
    quarta-feira, 16 de setembro de 2009 19:41
    Moderador
  • Agora sim.. Obrigado...

    Nem imaginava que tinha que criar isso do lado do cliente... agora, ao fazer o proxy, isso poderia ser default né?... mas enfim..

    uma pergunta.. esse certificado que eu gerei, já é o suficiente para fazer a autenticação né? estou fazendo o teste na minha máquina mesmo.. outra estação acessando esse serviço.. basta fazer essa configuração, e passar o user e pass né?

    Obrigado

    quarta-feira, 16 de setembro de 2009 20:46
  • Boas Savoia,

    Grande parte das configurações padrão são sempre mais restritiva, e neste caso o valor padrão é ChainTrust, ou seja, instrui o WCF a confiar no certificado somente se ele foi emitido através de um orgão como Verisign, Serasa, etc.

    Para testes isso é o suficiente, mas em ambiente de produção, o correto é recorrer a algum orgão (como Verisign, Serasa, etc.) para comprar esse certificado.
    http://www.israelaece.com
    quinta-feira, 17 de setembro de 2009 10:53
    Moderador
  • Amigo, siga os seguintes passos:

    makecert -n "CN=RootCATest" -r -sv RootCATest.pvk RootCATest.cer
    makecert -crl -n "CN=RootCATest" -r -sv RootCATest.pvk RootCATest.crl
    makecert -sk MyKeyName -iv RootCATest.pvk -n "CN=tempCert" -ic RootCATest.cer -sr localmachine -ss my -sky exchange -pe

    Encontre a PrivateKey, se for Windows Vista estará no diretorio abaixo:
    C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys

    Caso contrario baixe o aplicativo FindPrivateKey.exe e execute a rotina abaixo, ela lhe retornará a private key do certificado citado, no caso tempCert.

    FindPrivateKey.exe My LocalMachine -n "CN=tempCert"

    Algo que voce deve fazer é aplicar a permissão a essas chaves ao Servico de Rede, caso o seu windows seja ingles, substitua para "NETWORKING SERVICE" ao inves de "SERVIÇO DE REDE"

    cacls.exe "C:\Documents and Settings\All Users\Application Data\Microsoft\Crypto\RSA\Machinekeys\c97679a3da9a0576cff48d08cdd48389_584ea20d-bfa5-4665-b443-b3ee50747ee0" /E /G "SERVIÇO DE REDE":R

    cacls.exe "C:\Documents and Settings\All Users\Application Data\Microsoft\Crypto\RSA\Machinekeys\c97679a3da9a0576cff48d08cdd48389_584ea20d-bfa5-4665-b443-b3ee50747ee0

    makecert -n "CN=RootCATest" -r -sv RootCATest.pvk RootCATest.cer

    O .config do seu serviço deverá ter algumas definições:

    <

     

     

    bindings>
        <
    netTcpBinding>
            <
    binding name="TcpServiceBindingConfig">
                <
    security mode="Message">
                    <
    message clientCredentialType="UserName" />
                    <
    transport clientCredentialType="None" protectionLevel="None" />
                </
    security>
            </
    binding>
        </
    netTcpBinding>
    </
    bindings>

    <
    services>
        <
    service behaviorConfiguration="ServiceBehavior" name="Business.ServiceFacade">
            <endpoint address="net.tcp://localhost:808/Service.svc" binding="netTcpBinding"
                bindingConfiguration="TcpServiceBindingConfig"
                contract="Services.Contracts.IServiceContract" />
            <
    endpoint address="net.tcp://localhost:808/Service.svc/mex" binding="mexTcpBinding"
                contract="IMetadataExchange" />
        </
    service>
    </
    services>

    <
    behaviors>
        <
    serviceBehaviors>
            <
    behavior name="ServiceBehavior">
                <
    serviceMetadata httpGetEnabled="true" />
                <
    serviceDebug includeExceptionDetailInFaults="true" />
                <
    serviceCredentials>
                    <
    serviceCertificate
                        findValue="tempCert"
                        x509FindType="FindBySubjectName"
                        storeName="My"
                        storeLocation="LocalMachine" />
                    <
    userNameAuthentication userNamePasswordValidationMode="Custom
                         customUserNamePasswordValidatorType="MySecurity.FnacAuthentication, MySecurity" />
                </
    serviceCredentials>
            </
    behavior>
        </
    serviceBehaviors>
    </
    behaviors>


    O .config do seu client deverá ter algumas definições:

    <

     

     

    bindings>
        <
    netTcpBinding>
            <binding name="TcpClientBindingConfig">
                <
    security mode="Message">
                    <
    message clientCredentialType="UserName"/>
                    <
    transport clientCredentialType="None" protectionLevel="None"/>
                </
    security>
            </
    binding>
        </
    netTcpBinding>
    </
    bindings>

    <

     

     

    client>
        <
    endpoint name="TcpProdutoService"
                    address="net.tcp://localhost:808/Service.svc"
                    contract="Services.Contracts.IProdutoServiceContract"
                    binding="netTcpBinding"
                    bindingConfiguration="TcpClientBindingConfig"
                    behaviorConfiguration="ClientBehavior">
            <
    identity>
                <
    certificate
                    encodedValue="+YfyLHlDHuTySegXe7BgM9x/s9+Bkm9Xd2bkhuyF2h/K+WpHj0x8dJ7G1vmPcvF3ogK0sduXcJg8kP9A6TJd+......." />
            </
    identity>
        </
    endpoint>
    </
    client>

    Esse encodedValue voce poderá obter automaticamente se criar o serviço através do WebReference no proprio VisualStudio.

    <behaviors>
        <
    endpointBehaviors>
            <
    behavior name="ClientBehavior">
                <
    clientCredentials>
                    <
    serviceCertificate>
                        <
    authentication certificateValidationMode="None"/>
                        </serviceCertificate>
                </
    clientCredentials>
            </
    behavior>
        </
    endpointBehaviors>
    </
    behaviors>


    Acho que isso lhe ajudará...

    Abs.,
    Marcel Piva


    Marcel Piva
    quinta-feira, 17 de setembro de 2009 20:06