【问题标题】:.net WCF - CXF/WSS4j interoperability.net WCF - CXF/WSS4j 互操作性
【发布时间】:2011-01-22 14:39:16
【问题描述】:

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

我的问题是:如何实现一个 C# WS 客户端,它产生与以下客户端 java 代码相同的 SOAP 请求?

//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;

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

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

谢谢拉迪斯拉夫!我采纳了您的建议,并提出了类似的建议:

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();

因此,我得到(服务器端)以下 CXF 异常:

 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)

因此,这似乎是一个关键的 jks->pem 转换问题......或者我在上面的客户端代码中遗漏了什么?

【问题讨论】:

  • 我知道这是一个非常古老的问题,但我现在正在尝试做类似的事情,但不幸的是我做不到。我试过你的代码,但我不能引用UsernameClientCredentials 这是你的自定义类吗?基本上我必须使用 UsernameToken、BinarySecurityToken 和 Signature 来创建安全标头
  • @Misiu 你找到解决这种情况的方法了吗?
  • @Tagi 抱歉回复晚了。我创建了一个实现IClientMessageInspector 的自定义类,基本上它是手动创建XML 请求。遗憾的是,我再也无法访问源代码了。
  • @Misiu 您是创建了一个完整的请求还是仅创建了一个安全标头?感谢您的回复。
  • @Tagi 如果我没记错的话,我只添加了整个安全标头。

标签: wcf cxf ws-security


【解决方案1】:

好吧,最终解决方案是加密并签署整个用户名令牌。至于互操作性,必须在 cxf 中激活 ws 寻址,并且需要在 c# 中自定义绑定。成功的自定义绑定基本上是

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

Wcf 对每个 ws 寻址元素进行签名,因此服务器端也必须这样做。

【讨论】:

    【解决方案2】:

    这通常是一个很大的问题,因为 WCF does not support UserNameToken Profile with Digested password。几个月前我needed it,我们不得不实现我们自己的自定义绑定,但该代码还没有准备好发布。幸运的是this blog article 描述了其他实现,并包含带有新的UserNameClientCredentials 类支持摘要密码的示例代码。

    顺便说一句。使用称为 WSE 3.0 的旧 API 应该可以实现相同的安全配置。它已被 WCF 取代,但使用该 API 和旧的 ASMX 服务,一些 WS-* 堆栈配置仍然要简单得多。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-07
      • 2011-01-20
      • 2011-06-15
      • 1970-01-01
      相关资源
      最近更新 更多