You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WCF .NET调用带WS Security的Java Web服务的配置实现问题

配置调整方案

1. 修改绑定与客户端行为配置,输出X509IssuerSerial结构

修改你的WCF配置,调整安全节点的令牌引用样式为IssuerSerial,同时配置客户端证书:

<customBinding>
  <binding name="DigitalSignature">
    <textMessageEncoding messageVersion="Soap12" />
    <security 
      defaultAlgorithmSuite="Basic128Rsa15" 
      enableUnsecuredResponse="true"
      authenticationMode="MutualCertificate" 
      includeTimestamp="false"
      messageSecurityVersion="WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10">
      <localClientSettings 
        securityTokenReferenceStyle="IssuerSerial"
        includeTimestamp="false" />
    </security>
    <!-- 配置HTTP Basic认证 -->
    <httpTransport authenticationScheme="Basic" />
  </binding>
</customBinding>

<behaviors>
  <endpointBehaviors>
    <behavior name="ClientCertBehavior">
      <clientCredentials>
        <!-- 配置客户端签名证书,替换为你实际的证书查询参数 -->
        <clientCertificate 
          findValue="证书指纹" 
          storeLocation="CurrentUser" 
          storeName="My" 
          x509FindType="FindByThumbprint" />
        <!-- 不需要验证服务端证书的话可设置为None,生产环境建议按实际规则校验 -->
        <serviceCertificate>
          <authentication certificateValidationMode="None" />
        </serviceCertificate>
      </clientCredentials>
    </behavior>
  </endpointBehaviors>
</behaviors>

<!-- 关联配置到服务端点 -->
<endpoint 
  address="你的Java服务地址"
  binding="customBinding"
  bindingConfiguration="DigitalSignature"
  contract="你生成的服务契约接口名"
  behaviorConfiguration="ClientCertBehavior" />

2. 配置Basic认证凭据

在初始化服务客户端时设置Basic认证的用户名密码:

var client = new YourServiceClient();
client.ClientCredentials.UserName.UserName = "你的Basic认证用户名";
client.ClientCredentials.UserName.Password = "你的Basic认证密码";

3. 自定义消息拦截器补全规范化命名空间配置

WCF默认不会生成InclusiveNamespaces节点,需要实现客户端消息拦截器修改请求报文:

using System;
using System.IO;
using System.Xml;
using System.ServiceModel;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Description;
using System.ServiceModel.Channels;

public class WsSecurityMessageInspector : IClientMessageInspector
{
    public void AfterReceiveReply(ref Message reply, object correlationState)
    {
        // 无响应处理需求可留空
    }

    public object BeforeSendRequest(ref Message request, IClientChannel channel)
    {
        var buffer = request.CreateBufferedCopy(int.MaxValue);
        var xmlDoc = new XmlDocument();
        using (var ms = new MemoryStream())
        using (var writer = XmlWriter.Create(ms))
        {
            buffer.CreateMessage().WriteMessage(writer);
            writer.Flush();
            ms.Position = 0;
            xmlDoc.Load(ms);
        }

        var nsManager = new XmlNamespaceManager(xmlDoc.NameTable);
        nsManager.AddNamespace("ds", "http://www.w3.org/2000/09/xmldsig#");
        nsManager.AddNamespace("wsse", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");

        // 移除默认生成的BinarySecurityToken节点(你的目标报文不需要该节点)
        var bstNode = xmlDoc.SelectSingleNode("//wsse:BinarySecurityToken", nsManager);
        bstNode?.ParentNode.RemoveChild(bstNode);

        // 给CanonicalizationMethod节点添加s u前缀的InclusiveNamespaces
        var rootCanonicalNode = xmlDoc.SelectSingleNode("//ds:SignedInfo/ds:CanonicalizationMethod", nsManager) as XmlElement;
        if (rootCanonicalNode != null)
        {
            var incNode = xmlDoc.CreateElement("ec", "InclusiveNamespaces", "http://www.w3.org/2001/10/xml-exc-c14n#");
            incNode.SetAttribute("PrefixList", "s u");
            rootCanonicalNode.AppendChild(incNode);
        }

        // 给Transform下的CanonicalizationMethod节点添加u前缀的InclusiveNamespaces
        var transformCanonicalNode = xmlDoc.SelectSingleNode("//ds:Transform/ds:CanonicalizationMethod", nsManager) as XmlElement;
        if (transformCanonicalNode != null)
        {
            var incNode = xmlDoc.CreateElement("ec", "InclusiveNamespaces", "http://www.w3.org/2001/10/xml-exc-c14n#");
            incNode.SetAttribute("PrefixList", "u");
            transformCanonicalNode.AppendChild(incNode);
        }

        // 重新生成请求消息
        using (var ms = new MemoryStream())
        using (var writer = XmlWriter.Create(ms))
        {
            xmlDoc.WriteTo(writer);
            writer.Flush();
            ms.Position = 0;
            var reader = XmlReader.Create(ms);
            request = Message.CreateMessage(reader, int.MaxValue, request.Version);
        }
        return null;
    }
}

// 注册拦截器的端点行为
public class WsSecurityEndpointBehavior : IEndpointBehavior
{
    public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { }
    public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
    {
        clientRuntime.MessageInspectors.Add(new WsSecurityMessageInspector());
    }
    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { }
    public void Validate(ServiceEndpoint endpoint) { }
}

初始化客户端时注册该行为:

client.Endpoint.Behaviors.Add(new WsSecurityEndpointBehavior());

内容的提问来源于stack exchange,提问作者Jonathan Ayoub

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 05:18:03