本文介绍了.net WCF-CXF / WSS4j互操作性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想从.net c#客户端使用CXF Web服务。我们目前正在处理Java到Java的请求,并且通过ws-security(WSS4J库)保护SOAP信封。



我的问题是:如何实现C# WS-client产生与以下客户端Java代码相同的SOAP请求?

  // doc是原始的SOAP信封用WSS4J 
WSSecHeader secHeader = new WSSecHeader()处理;
secHeader.insertSecurityHeader(doc);

//添加带有密码摘要的用户名令牌
WSSecUsernameToken usrNameTok = new WSSecUsernameToken();
usrNameTok.setPasswordType(WSConstants.PASSWORD_DIGEST);
usrNameTok.setUserInfo( guest,psw_guest);
usrNameTok.prepare(doc);
usrNameTok.appendToHeader(secHeader);

//用客户端密钥
在信封主体上签名WSSecSignature sign = new WSSecSignature();
sign.setUserInfo( clientx509v1,psw_clientx509v1);
sign.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);

DocumentsignedDoc = null;
sign.prepare(doc,sigCrypto,secHeader);
SignedDoc = sign.build(doc,sigCrypto,secHeader);

//使用服务器公钥
加密信封主体WSSecEncrypt crypto = new WSSecEncrypt();
crypto.setUserInfo( serverx509v1);

//构建加密的SOAP部分
String out = null;
DocumentcryptedDoc = crypto.build(signedDoc,encCrypto,secHeader);
返回encryptedDoc;

有人知道我在哪里可以找到Microsoft how-to或.net工作示例吗?



==============================编辑== =================================



谢谢你拉迪斯拉夫!我应用了您的建议,然后想到了这样的东西:

  X509Certificate2 client_pk,server_cert; 
client_pk =新的X509Certificate2(@ C:\x509\clientKey.pem, blablabla);
server_cert =新的X509Certificate2(@ C:\x509\server-cert.pfx, blablabla);

//创建绑定。
System.ServiceModel.WSHttpBinding myBinding = new WSHttpBinding();
myBinding.TextEncoding = ASCIIEncoding.UTF8;
myBinding.MessageEncoding = WSMessageEncoding.Text;
myBinding.Security.Mode = SecurityMode.Message;
myBinding.Security.Message.ClientCredentialType = MessageCredentialType.Certificate;
myBinding.Security.Message.AlgorithmSuite =
System.ServiceModel.Security.SecurityAlgorithmSuite.Basic128;

//禁用凭据协商和
//安全上下文的建立。
myBinding.Security.Message.NegotiateServiceCredential = false;
myBinding.Security.Message.EstablishSecurityContext = false;

//创建端点地址。
EndpointAddress ea =
新EndpointAddress(新Uri( http://bla.bla.bla),
EndpointIdentity.CreateDnsIdentity( issuer)));

//在通道工厂上配置用户名凭据
UsernameClientCredentials凭据= new UsernameClientCredentials(new
UsernameInfo( superadmin, secret)));

//创建客户端。
PersistenceClient客户=新的PersistenceClient(myBinding,ea);

client.Endpoint.Contract.ProtectionLevel =
System.Net.Security.ProtectionLevel.EncryptAndSign;

//将ClientCredentials替换为UsernameClientCredentials
client.Endpoint.Behaviors.Remove(typeof(ClientCredentials));
client.Endpoint.Behaviors.Add(credentials);

//指定用于认证客户端的证书。
client.ClientCredentials.ClientCertificate.Certificate = client_pk;

//指定服务的默认证书。
client.ClientCredentials.ServiceCertificate.DefaultCertificate = server_cert;

//开始使用客户端。
client.Open();
clientProxyNetwork []响应= client.GetAllNetwork();

结果,我(服务器端)收到以下CXF异常:

  java.security.SignatureException:签名不匹配。 
在sun.security.x509.X509CertImpl.verify(X509CertImpl.java:421)
在sun.security.provider.certpath.BasicChecker.verifySignature(BasicChecker.java:133)
在sun .security.provider.certpath.BasicChecker.check(BasicChecker.java:112)
在sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(PKIXMasterCertPathValidator.java:117)

因此,似乎是一个关键的jks-> pem转换问题...还是我上面的客户端代码中缺少某些内容?

解决方案

最后,解决方案是对整个用户名令牌进行加密和签名。至于互操作性,必须在cxf中激活ws寻址,并且需要在c#中进行自定义绑定。达到目的的自定义绑定基本上是

  AsymmetricSecurityBindingElement abe = 
(AsymmetricSecurityBindingElement)SecurityBindingElement。
CreateMutualCertificateBindingElement(MessageSecurityVersion。
WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10);

Wcf在每个ws寻址元素上签名,因此必须在服务器端执行相同的操作。 / p>

I would like to consume a CXF web-service from a .net c# client. We are currently working with java-to-java requests and we protect SOAP envelopes through ws-security (WSS4J library).

My question is: how can I implement a C# WS-client which produces the same SOAP requests as the following client-side java code?

//doc is the original SOAP envelope to process with WSS4J
WSSecHeader secHeader = new WSSecHeader();
secHeader.insertSecurityHeader(doc);

//add username token with password digest
WSSecUsernameToken usrNameTok = new WSSecUsernameToken();
usrNameTok.setPasswordType(WSConstants.PASSWORD_DIGEST);
usrNameTok.setUserInfo("guest",psw_guest);
usrNameTok.prepare(doc);
usrNameTok.appendToHeader(secHeader);

//sign the envelope body with client key
WSSecSignature sign = new WSSecSignature();
sign.setUserInfo("clientx509v1", psw_clientx509v1);
sign.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);

Document signedDoc = null;
sign.prepare(doc, sigCrypto, secHeader);
signedDoc = sign.build(doc, sigCrypto, secHeader);

//encrypt envelope body with server public key
WSSecEncrypt encrypt = new WSSecEncrypt();
encrypt.setUserInfo("serverx509v1");

// build the encrypted SOAP part
String out = null;
Document encryptedDoc = encrypt.build(signedDoc, encCrypto, secHeader);
return encryptedDoc;

Does anybody know where I could find a microsoft how-to or a .net working example?

================================ EDIT ====================================

Thank you Ladislav! I applied your suggestions and I came up with something like:

X509Certificate2 client_pk, server_cert;
client_pk = new X509Certificate2(@"C:\x509\clientKey.pem", "blablabla");
server_cert = new X509Certificate2(@"C:\x509\server-cert.pfx", "blablabla");

// Create the binding.
System.ServiceModel.WSHttpBinding myBinding = new WSHttpBinding();
myBinding.TextEncoding = ASCIIEncoding.UTF8;
myBinding.MessageEncoding = WSMessageEncoding.Text;
myBinding.Security.Mode = SecurityMode.Message;
myBinding.Security.Message.ClientCredentialType = MessageCredentialType.Certificate;
myBinding.Security.Message.AlgorithmSuite =
            System.ServiceModel.Security.SecurityAlgorithmSuite.Basic128;

// Disable credential negotiation and the establishment of
// a security context.
myBinding.Security.Message.NegotiateServiceCredential = false;
myBinding.Security.Message.EstablishSecurityContext = false;

// Create the endpoint address.
EndpointAddress ea =
    new EndpointAddress(new Uri("http://bla.bla.bla"),
            EndpointIdentity.CreateDnsIdentity("issuer"));

// configure the username credentials on the channel factory
UsernameClientCredentials credentials = new UsernameClientCredentials(new
                                    UsernameInfo("superadmin", "secret"));

// Create the client.
PersistenceClient client = new PersistenceClient(myBinding, ea);

client.Endpoint.Contract.ProtectionLevel =
            System.Net.Security.ProtectionLevel.EncryptAndSign;

// replace ClientCredentials with UsernameClientCredentials
client.Endpoint.Behaviors.Remove(typeof(ClientCredentials));
client.Endpoint.Behaviors.Add(credentials);

// Specify a certificate to use for authenticating the client.
client.ClientCredentials.ClientCertificate.Certificate = client_pk;

// Specify a default certificate for the service.
client.ClientCredentials.ServiceCertificate.DefaultCertificate = server_cert;

// Begin using the client.
client.Open();
clientProxyNetwork[] response = client.GetAllNetwork();

As a result I get (server-side) the following CXF exception:

 java.security.SignatureException: Signature does not match.
at sun.security.x509.X509CertImpl.verify(X509CertImpl.java:421)
at sun.security.provider.certpath.BasicChecker.verifySignature(BasicChecker.java:133)
at sun.security.provider.certpath.BasicChecker.check(BasicChecker.java:112)
at sun.security.provider.certpath.PKIXMasterCertPathValidator.validate  (PKIXMasterCertPathValidator.java:117)

Therefore it seems a key jks->pem conversion problem... Or am I am missing something in the client-code above?

解决方案

Well, in the end the solution is to encrypt and sign the whole username token. As for the interoperability, the ws addressing must be activated in cxf and a custom binding in c# is needed. The custom binding that did the trick is basically

AsymmetricSecurityBindingElement abe =
    (AsymmetricSecurityBindingElement)SecurityBindingElement.
CreateMutualCertificateBindingElement(MessageSecurityVersion.
WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10);
               

Wcf signs each ws addressing element, therefore the same must be done server side.

这篇关于.net WCF-CXF / WSS4j互操作性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-15 20:29