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

C#调用SOAP API配置wsse认证报UsernameToken缺失如何解决

问题根因

你当前配置返回UsernameToken not present错误的核心原因是:BasicHttpsSecurityMode.Transport模式仅会启用HTTPS传输层的身份校验逻辑,不会在SOAP消息头中注入WS-Security规范要求的wsse:Security/UsernameToken节点,服务端解析请求时找不到对应认证头,直接返回认证失败。

解决方案

根据服务端对WSSE头格式的兼容程度,可选择以下两种方案:

方案1:调整绑定安全模式(适配标准WS-Security服务)

修改绑定的安全模式为「传输层加密+消息层凭证」,指定消息凭证类型为用户名,WCF会自动在SOAP头中生成符合规范的UsernameToken节点,保留你原来的ClientCredentials赋值逻辑即可。

BasicHttpsBinding bindingHttps = new BasicHttpsBinding();
// 关键修改:替换纯Transport模式
bindingHttps.Security.Mode = BasicHttpsSecurityMode.TransportWithMessageCredential;
// 指定消息层使用用户名凭证,对应WS-Security的UsernameToken
bindingHttps.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;
bindingHttps.MaxReceivedMessageSize = 500000000; 
bindingHttps.SendTimeout = new TimeSpan(0, 5, 0);

// 原有凭证赋值逻辑保留
client.ClientCredentials.UserName.UserName = "XXXXXXXXX";
client.ClientCredentials.UserName.Password = "XXXXXXXXX";

方案2:自定义消息检查器手动注入认证头(适配格式要求严格的服务)

如果方案1配置后仍报错,说明服务端对WSSE头格式有严格要求(比如不允许默认生成的Nonce、Created节点,或指定密码明文类型),可以直接自定义客户端消息检查器,完全按照服务端给出的XML格式构造认证头注入,完全避免WCF自动生成的头格式不匹配问题。

  1. 实现自定义消息检查器和端点行为
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using System.Xml;

public class WSSESecurityInspector : IClientMessageInspector
{
    private readonly string _username;
    private readonly string _password;
    private const string WsseNamespace = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";

    public WSSESecurityInspector(string username, string password)
    {
        _username = username;
        _password = password;
    }

    public object BeforeSendRequest(ref Message request, IClientChannel channel)
    {
        XmlDocument doc = new XmlDocument();
        string securityXml = $@"<wsse:Security xmlns:wsse=""{WsseNamespace}"">
            <wsse:UsernameToken>
                <wsse:Username>{_username}</wsse:Username>
                <wsse:Password Type=""http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText"">{_password}</wsse:Password>
            </wsse:UsernameToken>
        </wsse:Security>";
        
        using XmlReader reader = XmlReader.Create(new StringReader(securityXml));
        XmlElement securityElement = (XmlElement)doc.ReadNode(reader);
        request.Headers.Add(securityElement);
        return null;
    }

    public void AfterReceiveReply(ref Message reply, object correlationState) { }
}

public class WSSEBehavior : IEndpointBehavior
{
    private readonly string _username;
    private readonly string _password;

    public WSSEBehavior(string username, string password)
    {
        _username = username;
        _password = password;
    }

    public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
    {
        clientRuntime.ClientMessageInspectors.Add(new WSSESecurityInspector(_username, _password));
    }

    public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { }
    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { }
    public void Validate(ServiceEndpoint endpoint) { }
}
  1. 客户端初始化时注入自定义行为
// 初始化客户端和绑定后,添加自定义WSSE头行为
client.Endpoint.EndpointBehaviors.Add(new WSSEBehavior("你的用户名", "你的密码"));
注意事项
  • 使用方案2时,不需要再设置ClientCredentials.UserName,避免重复生成认证头
  • 构造Security节点时必须保证wsse前缀对应的命名空间和服务端要求一致,否则服务端无法识别节点
  • 如果服务端要求密码为摘要类型,只需要修改Password节点的Type属性和值的生成逻辑即可

内容的提问来源于stack exchange,提问作者Lorenzo Cacciola

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 08:33:11