C# WCF 服务,阅读soapenv 标头安全部分
Posted
技术标签:
【中文标题】C# WCF 服务,阅读soapenv 标头安全部分【英文标题】:C# WCF Service, read soapenv header security section 【发布时间】:2021-06-24 02:30:14 【问题描述】:我正在寻找一种解决方法来读取传入的 soapenv => 安全部分。
我一直在尝试从传入的请求中获取soapenv,但没有成功:
int operationIndex = OperationContext.Current.IncomingMessageHeaders.FindHeader("Security", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
string operation = OperationContext.Current.IncomingMessageHeaders.GetHeader<string>(operationIndex);
这是一个关于如何格式化标题的示例:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/">
<soapenv: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">
<wsse:UsernameToken wsu:Id="UsernameToken-1">
<wsse:Username>TheUsername</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">XXXXXXXXXXXXXXXX</wsse:Password>
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">XXXXXXXXXXXXX</wsse:Nonce>
<wsu:Created>XXXXXXXXXX</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<tem:AMethod>
<!--Optional:-->
<tem:field>2</tem:field>
</tem:AMethod>
</soapenv:Body>
</soapenv:Envelope>
还有其他方法可以读取传入的肥皂标题吗?
编辑
刚刚找到了另一种获取soapheader的方法
var headerContent = OperationContext.Current.IncomingMessageHeaders.Select((value, i) => new i, value ).ToList().Where(x => x.value.Name.ToLower().Equals("security")).FirstOrDefault();
XmlDictionaryReader xr = OperationContext.Current.IncomingMessageHeaders.GetReaderAtHeader(headerContent.i);
string xmlSecurityHeader = xr.ReadOuterXml();
【问题讨论】:
没有运气是什么意思?操作指数是-1还是别的?IncomingMessageHeaders
实现 IEnumerable
。您是否尝试枚举所有标题以查看其中的内容?
我刚刚找到了另一种获取相关标头的方法:code
var headerContent = OperationContext.Current.IncomingMessageHeaders.Select((value, i) => new i, value ).ToList( ).Where(x => x.value.Name.ToLower().Equals("security")).FirstOrDefault(); XmlDictionaryReader xr = OperationContext.Current.IncomingMessageHeaders.GetReaderAtHeader(headerContent.i);字符串 xmlSecurityHeader = xr.ReadOuterXml() code
【参考方案1】:
可以试试messageinspector,在客户端实现IClientMessageInspector接口,在服务端实现IDispatchMessageInspector接口。您可以拦截请求和回复。
这是客户端上的示例:
public class ClientMessageLogger : IClientMessageInspector
public void AfterReceiveReply(ref Message reply, object correlationState)
string outputstr = $"Server reply message received by the client:\nreply\n";
Console.WriteLine(outputstr);
public object BeforeSendRequest(ref Message request, IClientChannel channel)
string outputText = $"The request message that the client will send:\nrequest\n";
Console.WriteLine(outputText);
return null;
[AttributeUsage(AttributeTargets.Interface)]
public class CustomBehavior : Attribute, IContractBehavior
public Type TargetContract => typeof(ServiceReference1.ICalculator);
public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
return;
public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
clientRuntime.ClientMessageInspectors.Add(new ClientMessageLogger());
public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
return;
public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
return;
这是服务器上的示例:
public class CustomMessageInspector : IDispatchMessageInspector
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
string displayText = $"The request message received by the server:\nrequest\n";
Console.WriteLine(displayText);
return null;
public void BeforeSendReply(ref Message reply, object correlationState)
string displayText = $"Server reply message:\nreply\n";
Console.WriteLine(displayText);
[AttributeUsage(AttributeTargets.Interface)]
public class CustomBehavior : Attribute, IContractBehavior
public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
return;
public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
return;
public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
dispatchRuntime.MessageInspectors.Add(new CustomMessageInspector());
public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
return;
最后在接口上方添加[CustomBehavior]
,在客户端,接口在你的服务引用中。
【讨论】:
以上是关于C# WCF 服务,阅读soapenv 标头安全部分的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Jquery Ajax 发送自定义标头并使用 C# 在 WCF 服务中检索相同的标头值?
C#消费soap WS在VerifyIncomingMessage中返回安全头错误
SOAP WCF 将 Signature 和 BinarySecurityToken 添加到标头