WCF服务Security头部未识别问题及签名配置求助
问题场景
创建WCF服务后,通过soapUI发送包含WS-Security签名头部的SOAP请求时,服务返回以下错误:
The header 'Security' from the namespace 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd' was not understood by the recipient of this message, causing the message to not be processed. This error typically indicates that the sender of this message has enabled a communication protocol that the receiver cannot process. Please ensure that the configuration of the client's binding is consistent with the service's binding
配置证书验证后,服务出现警告:Message with action '' has no message signature parts specified.(中文翻译:“动作为空的消息未指定签名部分”)
请求内容
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Header> <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> <ds:SignedInfo> <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#gost34310-gost34311"/> <ds:Reference URI="test"> <ds:Transforms> <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> </ds:Transforms> <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#gost34311"/> <ds:DigestValue>test</ds:DigestValue> </ds:Reference> </ds:SignedInfo> <ds:SignatureValue> test </ds:SignatureValue> <ds:KeyInfo> <wsse:SecurityTokenReference> <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"> test </wsse:KeyIdentifier> </wsse:SecurityTokenReference> </ds:KeyInfo> </ds:Signature> </wsse:Security> </SOAP-ENV:Header> <S:Body xmlns:ns2="http://bip.bee.kz/SyncChannel/v10/Types" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="test"> <ns2:SendMessage> <request> <requestInfo> <test>test</test> <sender> <test>test</test> </sender> <sessionId>test</sessionId> </requestInfo> <requestData> <data> <test>test</test> </data> </requestData> </request> </ns2:SendMessage> </S:Body> </S:Envelope>
服务代码
public class Service : IService { public string SendMessage(SendMessage request) { return "test"; } }
模型定义
[MessageContract(WrapperName="SendMessage", IsWrapped=true, WrapperNamespace = "")] public class SendMessage { [MessageBodyMember(Namespace = "", Name = "request")] public Request Request { get; set; } } [Serializable] [XmlType(Namespace = "")] public class Request { [XmlElement(ElementName = "requestInfo", Order = 0)] public RequestInfo RequestInfo { get; set; } [XmlElement(ElementName = "requestData", Order = 1)] public RequestData RequestData { get; set; } }
初始配置
<system.serviceModel> <behaviors> <serviceBehaviors> <behavior> <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/> <serviceDebug includeExceptionDetailInFaults="false"/> </behavior> </serviceBehaviors> </behaviors> <protocolMapping> <add binding="basicHttpsBinding" scheme="https"/> </protocolMapping> <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/> </system.serviceModel> <system.webServer> <modules runAllManagedModulesForAllRequests="true"/> <directoryBrowse enabled="true"/> </system.webServer>
配置证书验证后的配置片段
<services> <service behaviorConfiguration="ServiceBehavior" name="Service"> <endpoint address="" binding="customBinding" bindingConfiguration="ServiceBinding" name="ConclusionService" contract="IService" /> </service> </services> <behavior name="ServiceBehavior"> <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" /> <serviceDebug includeExceptionDetailInFaults="true" /> <serviceCredentials> <serviceCertificate findValue="test" storeLocation="CurrentUser" x509FindType="FindBySubjectName" /> </serviceCredentials> </behavior> <customBinding> <binding name="ServiceBinding"> <security authenticationMode="AnonymousForCertificate" requireDerivedKeys="false" messageProtectionOrder="SignBeforeEncrypt" messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10" /> <textMessageEncoding messageVersion="Soap11WSAddressingAugust2004" /> <httpTransport /> </binding> </customBinding>
解决方案
1. 初始错误根源
初始使用的basicHttpsBinding仅支持传输层HTTPS安全,不处理消息级的WS-Security头部,因此无法识别请求中的Security节点。必须改用支持WS-Security的绑定(如customBinding或wsHttpBinding)并配置对应的消息安全规则。
2. 修正CustomBinding配置
调整安全版本匹配请求
请求使用的是WS-Security 1.0规范(命名空间为http://docs.oasis-open.org/wss/2004/01/...),原配置中的messageSecurityVersion指定的是WS-Security 1.1,需改为WS-Security 1.0版本:
messageSecurityVersion="WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10"
指定签名消息部分
警告“动作为空的消息未指定签名部分”是因为未明确告知WCF需要对哪些消息元素进行签名验证。在<security>节点内添加<message>子节点配置签名规则:
<security authenticationMode="AnonymousForCertificate" requireDerivedKeys="false" messageProtectionOrder="SignBeforeEncrypt" messageSecurityVersion="WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10"> <message protectTokens="true" signatureConfirmation="false"> <secureConversationBootstrap /> </message> </security>
移除不必要的WS-Addressing
请求中未包含WS-Addressing头部,因此将textMessageEncoding的messageVersion改为Soap11即可:
<textMessageEncoding messageVersion="Soap11" />
3. 完善服务证书配置
确保服务证书正确安装在指定存储位置(CurrentUser或LocalMachine),findValue必须与证书的主题名或指纹完全匹配。同时添加客户端证书验证规则,确保服务信任客户端签名用的证书:
<serviceCredentials> <serviceCertificate findValue="你的证书主题名" storeLocation="CurrentUser" x509FindType="FindBySubjectName" /> <clientCertificate> <authentication certificateValidationMode="PeerOrChainTrust" /> </clientCertificate> </serviceCredentials>
4. 修正模型命名空间匹配请求
请求中的SendMessage属于命名空间http://bip.bee.kz/SyncChannel/v10/Types,但模型定义的命名空间为空,会导致服务无法正确解析请求体。调整模型的命名空间:
[MessageContract(WrapperName = "SendMessage", IsWrapped = true, WrapperNamespace = "http://bip.bee.kz/SyncChannel/v10/Types")] public class SendMessage { [MessageBodyMember(Namespace = "http://bip.bee.kz/SyncChannel/v10/Types", Name = "request")] public Request Request { get; set; } } [Serializable] [XmlType(Namespace = "http://bip.bee.kz/SyncChannel/v10/Types")] public class Request { [XmlElement(ElementName = "requestInfo", Order = 0, Namespace = "http://bip.bee.kz/SyncChannel/v10/Types")] public RequestInfo RequestInfo { get; set; } [XmlElement(ElementName = "requestData", Order = 1, Namespace = "http://bip.bee.kz/SyncChannel/v10/Types")] public RequestData RequestData { get; set; } }
5. GOST签名算法支持注意事项
请求中使用的gost34310-gost34311算法属于俄罗斯加密标准,WCF默认不支持。需要安装第三方加密库(如CryptoPro .NET),并配置WCF使用该加密提供程序才能验证此类签名。
内容的提问来源于stack exchange,提问作者zig8953

