我要实现的目标是在每个请求中将凭据/令牌传递给WCF服务。顺便说一句,此凭据不是Windows凭据,它们是从自定义数据库中获取的,并且身份验证逻辑非常简单,tenantId +用户名+密码。
我目前正在使用消息检查器将这些信息插入标头,并从服务器端检查器中获取(使用OperationContext
)。
但是为了保持线程安全,我必须将请求包装在每个winform请求中,如下所示:
using (new OperationContextScope((WcfService as ServiceClient).InnerChannel))
{
MessageHeader hdXXId = MessageHeader.CreateHeader("XXId", "CustomHeader", WinformSomeVariable.XXId);
OperationContext.Current.OutgoingMessageHeaders.Add(hdXXId);
_objXX = WcfService.GetXXById(id);
}
就像上面显示的那样,这很沉重,显然不是解决这种情况的明智方法。那么,有什么方法可以安全地保存此类信息,也可以在WCF检查器中获取它们?
非常感谢!
PS。感谢@Abraham Qian,我一直很傻。只需将客户检查器放在同一winform项目中即可解决此问题。
答案 0 :(得分:0)
暂时忽略一下如何重构身份验证的问题。 至于如何使用IClientMessageInspector接口创建持久消息标头,以下代码段可能会有用(假设使用Channel Factory进行调用)
class Program
{
static void Main(string[] args)
{
Uri uri = new Uri("http://localhost:1300");
IService service = ChannelFactory<IService>.CreateChannel(new BasicHttpBinding(), new EndpointAddress(uri));
try
{
Console.WriteLine(service.SayHello());
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
[ServiceContract(Namespace = "mydomain")]
[CustomContractBehavior]
public interface IService
{
[OperationContract]
string SayHello();
}
public class ClientMessageLogger : IClientMessageInspector
{
public void AfterReceiveReply(ref Message reply, object correlationState)
{
string displayText = $"the client has received the reply:\n{reply}\n";
Console.Write(displayText);
}
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
//Add custom message header
request.Headers.Add(MessageHeader.CreateHeader("myheader","mynamespace",2000));
string displayText = $"the client send request message:\n{request}\n";
Console.WriteLine(displayText);
return null;
}
}
public class CustomContractBehaviorAttribute : Attribute, IContractBehavior, IContractBehaviorAttribute
{
public Type TargetContract => typeof(IService);
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;
}
}