none
Problemas com Certificados + Java WS RRS feed

  • Pergunta

  • Olá Pessoal,

    Estou com o seguinte problema:

    Um cliente possui um WebService exposto em Java, com SOAP 1.1, onde tive que codificar um bind personalizado para funcionar, pois além da versão do SOAP, havia a necessidade de se utilizar WS Security - https, e também UsernameToken, somente com assinatura das partes da mensagem, sem criptografia, com certificados para o cliente e para o servidor.

    Tudo foi configurado corretamente e funciona, exceto pela seguinte questão: A idéia é permitir acesso deste WS por vários clientes, cada um com seu certificado.

    Porém, na sessão behaviors do app.config está especificado o certificado do servidor, e este não é o comportamento desejado - gostaríamos não precisar especificar este certificado (o que gera erro no momento da conexão - certificado não informado) ou então especificar não o certificado da empresa, mas sim o da CertSign - autoridade pai do certificado em questão, com ChainTrust ativado. Porém gera outro erro, indicando que o certificado usado na assinatura da msg de envio é diferente do usado na assinatura da msg de retorno.

    A idéia é não precisar repassar o certificado a todos os clientes sempre que o certificado for renovado.

    Como ter este cliente WCF se conectando ao servidor mas sem precisar instalar o certificado do servidor nos clientes?

    Obrigado!


    Leandro C. Almeida - MCP
    • Editado Leandro C. Almeida quarta-feira, 15 de setembro de 2010 21:14 Melhora da pergunta
    quarta-feira, 15 de setembro de 2010 20:20

Todas as Respostas

  • Boas Leandro,

    Mas a sua dificuldade é em alterar o certificado em tempo de execução?

    O serviço está utilizando o certificado apenas para proteger a mensagem ou está utilizando o certificado para autenticar o usuario?
    http://www.israelaece.com
    sábado, 18 de setembro de 2010 00:19
    Moderador
  • Olá Israel,

    Em primeiro lugar, obrigado pelo interesse em ajudar.

    O certificado é usado tanto para assinar a mensagem quanto para autenticar o usuário.

    Abaixo, segue o binding criado para tal:

     

    MyBinding.cs

        public class MyBinding : System.ServiceModel.Channels.Binding

        {

     

            public override BindingElementCollection CreateBindingElements()

            {

     

                BindingElementCollection be = new BindingElementCollection();

     

                X509SecurityTokenParameters initiator = new X509SecurityTokenParameters( X509KeyIdentifierClauseType.Thumbprint, SecurityTokenInclusionMode.AlwaysToRecipient);

                X509SecurityTokenParameters recipient = new X509SecurityTokenParameters(X509KeyIdentifierClauseType.Thumbprint, SecurityTokenInclusionMode.AlwaysToInitiator);

                AsymmetricSecurityBindingElement element = new AsymmetricSecurityBindingElement(recipient, initiator);

     

                element.SetKeyDerivation(false);

                element.IncludeTimestamp = true;

                element.AllowSerializedSigningTokenOnReply = true;

                element.MessageProtectionOrder = MessageProtectionOrder.SignBeforeEncrypt;

                element.MessageSecurityVersion = MessageSecurityVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10;

     

                UserNameSecurityTokenParameters tokenParameters = new UserNameSecurityTokenParameters();

     

                tokenParameters.InclusionMode = SecurityTokenInclusionMode.AlwaysToRecipient;

                tokenParameters.RequireDerivedKeys = false;

                element.EndpointSupportingTokenParameters.Signed.Add(tokenParameters);

     

                be.Add(element);

                be.Add(new TextMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8));

                be.Add(new HttpsTransportBindingElement());

     

                return be;

     

            }

     

            public override string Scheme

            {

                get { return "https"; }

            }

        }

     

    Behavior do App.config:

        <behaviors>

          <endpointBehaviors>

            <behavior name="AnbimaBehavior">

              <clientCredentials>

                <clientCertificate findValue="5d b4 a8 h0 33 21 d3 66 61 c2 23 f3 24 76 4d 9e 65 92 0f a2"

                x509FindType="FindByThumbprint" />

                <serviceCertificate>

                  <defaultCertificate findValue="5d b4 a8 h0 33 21 d3 66 61 c2 23 f3 24 76 4d 9e 65 92 0f a2"

                  x509FindType="FindByThumbprint" />

                  <authentication certificateValidationMode="None" />

                </serviceCertificate>

                <httpDigest impersonationLevel="Identification" />

              </clientCredentials>

            </behavior>

     

    Gostaríamos de não precisar especificar o serviceCertificate ou, caso especificar, que fosse o da CertSign, para não precisar enviar o certificado do servidor para o cliente final.

     

    Obrigado!

     


    Leandro C. Almeida - MCP
    terça-feira, 21 de setembro de 2010 16:54
  • Boas Leandro,

    Deixa ver se consigo te ajudar em algo. Você está se referindo ao certificado informado no elemento serviceCertificate?

    Se sim, esse certificado é utilizado para que o cliente valide o serviço, ou seja, evita que o cliente responda para um serviço falso. Esse elemento é utilizado para especificar as configurações utilizandas pelo cliente para validar o certificado apresentado pelo serviço durante a autenticação do HTTPS/SSL ou pode conter o certificado utilizado pelo serviço para criptografas as mensagens, quando se utiliza a segurança baseada na mensagem.
    http://www.israelaece.com
    quarta-feira, 22 de setembro de 2010 13:56
    Moderador
  • Ok Israel,

    Agora, para o cliente validar o serviço, eu precisarei entregar meu certificado do serviço (.cer) para meus clientes finais? (isso é o que não gostaríamos) O ideal seria que o app cliente validasse o serviço pela autoridade "pai" - a CertSign, onde não precisaria enviar meu certificado do serviço.

    Quando eu tento fazer isso, especificando o certificado, é gerado o seguinte erro, na resposta do serviço: "A mensagem de entrada foi assinada com um token diferente do usado para criptografar o corpo. Isto não era esperado".

    Analisando o trace, as mensagens trafegam, mas na validação da assinatura do corpo que o serviço manda, o WCF no cliente rejeita a assinatura, pois está diferente do especificado no certificado da CertSign. Dá para indicar qual o certificado/chave pública será usada para validar a assinatura do retorno?

    PS: Seu blog já me ajudou muito - parabéns pelo trabalho!


    Leandro C. Almeida - MCP
    quarta-feira, 22 de setembro de 2010 15:12
  • Boas Leandro,

    Já tentou remover o serviceCertificate do cliente e definir a propriedade NegotiateServiceCredential dos dois lados como True?
    http://www.israelaece.com
    quarta-feira, 22 de setembro de 2010 23:32
    Moderador
  • Olá Israel,

    Tentei seguir sua sugestão, porém não consegui testá-la até o fim, pois meu Binding é feito via código e não possui a propriedade Security.

    Eu cheguei a criar a propriedade na classe do binding (MyBinding) e também instanciei o objeto e setei a propriedade Security.Message.NegotiateServiceCredential p/ True no método CreateBindingElements().

    Depois removi do behavior (app.config) o serviceCertificate do cliente e o erro que recebi foi: "O certificado de serviço não é fornecido para o destino http... Especifique um certificado de serviço em ClientCredentials".

    Acho que a propriedade não surtiu efeito - talvez por causa do binding...

    Abs,


    Leandro C. Almeida - MCP
    sexta-feira, 24 de setembro de 2010 14:10
  • Boas Leandro,

    Em algum lugar, há algum tempo, eu vi que a negociação não é suportada em algumas plataformas, mas não sei te precisar se o Java fornece isso ou não. A negociação talvez resolva o seu problema, ou seja, evita a necessidade dos clientes terem acesso out-of-band a chave pública do certificado do serviço. (http://msdn.microsoft.com/en-us/library/ms733102(VS.90).aspx).

    Mas lendo mais calmamente o seu post inicial, você disse que o serviço foi desenvolvido em Java e você está tentando consumir via WCF? Se for isso, ai precisaremos ver se o serviço está expondo a chave pública para negociação ou somente out-of-band.


    http://www.israelaece.com
    sexta-feira, 24 de setembro de 2010 16:16
    Moderador