WS-Security do soapUI ao WCF - ligação e configuração
Preciso criar um cliente WCF para chamar um serviço sobre o qual não tenho controle e recebemos apenas um wsdl (com esquemas). O serviço da web usa o certificado X.509 com a especificação de WS-Security versão 1.0
O provedor de serviços da web compartilhou o xml bruto da mensagem soap para destacar o cabeçalho ws-security. Usando o soapUI, consegui criar exatamente o mesmo cabeçalho wsse-Security, como mostrado abaixo:
<soapenv:Envelope xmlns:oas="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:oas1="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xd="http://www.w3.org/2000/09/xmldsig#">
<soapenv:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<ds:Signature Id="SIG-32" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="#id-31">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<InclusiveNamespaces PrefixList="oas oas1 urn urn1 urn2 urn3 xd" xmlns="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>ucSFZEOTHpe/IOlPVWtU+1xT4sM=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>
d4CKqie==
</ds:SignatureValue>
<ds:KeyInfo Id="KI-9A8D1F611E86CFB79E144316684667546">
<wsse:SecurityTokenReference oas:Id="STR-9A8D1F611E86CFB79E144316684667547">
<wsse:KeyIdentifier EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"
ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3">5lAB5TaqeFwo23mRVm31LngBT1dQMf94mxeVkyKog==
</wsse:KeyIdentifier>
</wsse:SecurityTokenReference>
</ds:KeyInfo>
</ds:Signature>
<oas:Timestamp oas:Id="TS-30">
<oas:Created>2015-09-25T07:40:46.670Z</oas:Created>
<oas:Expires>2015-09-26T11:27:26.670Z</oas:Expires>
</oas:Timestamp>
</wsse:Security>
</soapenv:Header>
<soapenv:Body oas:Id="id-31">
...
</soapenv:Body>
</soapenv:Envelope>
No soapUI, nas "Configurações de segurança WS", adicionei os Keystores (jks com meu certificado particular) e os Truststores (jks com chave pública raiz da CA). Por fim, adicionei "Configurações de WS-Security de saída" com a seguinte configuração.
Com essa configuração do WS-Security, a mensagem soap adiciona owsse:Security
como mostrado acima.
Agora, estamos construindo o cliente WS no .NET com WCF e precisamos de ajuda com as configurações de Ligação e Segurança. Quais definições de ligação e configuração podem ser usadas para ter o mesmo cabeçalho WS-Security conforme necessário ou mostrado acima?
No WSDL, criei um proxy do lado do cliente usando WSCF.blue. Embora, eu também possa ter usado o svcutil.exe ou o recurso Adicionar Referência de Serviço do VS.
Tentei criar o código customBinding no seguinte, mas ao inspecionar esta mensagem, owsse
cabeçalho não é o mesmo que eu quero.
Por exemplo, ele adiciona umBinarySecurityToken
noSecurity
cabeçalho que não é desejado.
Ou oKeyIdentifier
éX509SubjectKeyIdentifier
ao invés deX509v3
por exemplo:<o:KeyIdentifier ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509SubjectKeyIdentifier" ...</o:KeyIdentifier>
Também adiciona múltiplosReference
debaixo deSignedInfo
e, apesar de passar na validação do esquema, não sei ao certo qualReference
está fazendo.
internal static Binding GetCustomBinding()
{
CustomBinding myBinding = new CustomBinding();
AsymmetricSecurityBindingElement asBindingElement = new AsymmetricSecurityBindingElement();
//Have tried these also
//asBindingElement.MessageSecurityVersion = MessageSecurityVersion.WSSecurity11WSTrust13WSSecureConversation13WSSecurityPolicy12;
//asBindingElement.MessageSecurityVersion = MessageSecurityVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10;
//WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10
asBindingElement.MessageSecurityVersion = MessageSecurityVersion.WSSecurity10WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10;
asBindingElement.InitiatorTokenParameters = new System.ServiceModel.Security.Tokens.X509SecurityTokenParameters { InclusionMode = SecurityTokenInclusionMode.Never };
asBindingElement.RecipientTokenParameters = new System.ServiceModel.Security.Tokens.X509SecurityTokenParameters
{
//X509ReferenceStyle = X509KeyIdentifierClauseType.SubjectKeyIdentifier,
InclusionMode = SecurityTokenInclusionMode.Never
};
asBindingElement.MessageProtectionOrder = System.ServiceModel.Security.MessageProtectionOrder.SignBeforeEncrypt;
//asBindingElement.SecurityHeaderLayout = SecurityHeaderLayout.Strict;
asBindingElement.SecurityHeaderLayout = SecurityHeaderLayout.LaxTimestampLast;
asBindingElement.EnableUnsecuredResponse = true;
asBindingElement.IncludeTimestamp = true;
asBindingElement.SetKeyDerivation(false);
asBindingElement.DefaultAlgorithmSuite = System.ServiceModel.Security.SecurityAlgorithmSuite.Basic128Rsa15;
asBindingElement.EndpointSupportingTokenParameters.Signed.Add(new X509SecurityTokenParameters());
myBinding.Elements.Add(asBindingElement);
myBinding.Elements.Add(new TextMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8));
//myBinding.Elements.Add(new MtomMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8));
HttpsTransportBindingElement httpsBindingElement = new HttpsTransportBindingElement();
httpsBindingElement.RequireClientCertificate = true;
myBinding.Elements.Add(httpsBindingElement);
return myBinding;
}
Além disso, estou usando esse comportamento para o certificado x509
<behaviors>
<endpointBehaviors>
<behavior name="MyBehavior">
<clientCredentials>
<clientCertificate findValue="xxx"
storeLocation="LocalMachine" storeName="My" x509FindType="FindByThumbprint" />
<serviceCertificate>
<defaultCertificate findValue="xxx"
storeLocation="LocalMachine" storeName="My" x509FindType="FindByThumbprint" />
<authentication certificateValidationMode="None" revocationMode="NoCheck"
trustedStoreLocation="LocalMachine" />
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>