服务端为java的cxfb的webservice。cxfb有自己的拦截器可以接受客户端的SOAPHeader认证信息。
实现webservice客户端代码思路的是,自己写了一个工具类,使用的单例模式。将每个接口封装成了静态方法。所有外部类通过工具类方法调用实现代码逻辑。
/// <summary>
/// 单例模式获取接口端调用
/// </summary>
/// <returns></returns>
private static CXFBServiceClient GetCommon()
{
if (CXFBServiceClient == null)
{
try
{
lock (lockHelper)
{
if (CXFBServiceClient == null)
{
CXFBServiceClient = new CXFBServiceClient();
}
}
}
catch (Exception ex)
{
Log.SetErrorLog("CXFBServices.GetCommon", ex.ToString(), ex);
}
}
return CXFBServiceClient;
}
#region 通用接口
/// <summary>
/// 获取ConfigCode表的键值对,可用于下拉菜单
/// </summary>
/// <param name="code">Config_Code数据</param>
/// <returns></returns>
public static ArrayList GetConfigcode(string code)
{
List<fbConfigCode> fbConfigCodes = new List<fbConfigCode>();
try
{
fbConfigCode[] fbConfigCodes_ = new fbConfigCode[0];
Log.SetInfoLog("CXFBServices.GetConfigcode.json.code", JsonConvert.SerializeObject(code), null);
fbConfigCodes_ = GetCommon().getConfigCode(code);
Log.SetInfoLog("CXFBServices.GetConfigcode.json", JsonConvert.SerializeObject(fbConfigCodes_), null);
if (fbConfigCodes_ != null && fbConfigCodes_.Length > 0)
{
fbConfigCodes = fbConfigCodes_.ToList();
}
}
catch (Exception ex)
{
Log.SetErrorLog("CXFBServices.GetConfigcode", ex.ToString(), ex);
}
ArrayList arrayList = new ArrayList();
fbConfigCodes?.ForEach(fbConfigCode =>
{
arrayList.Add(new DictionaryEntry(fbConfigCode.id, fbConfigCode.configName));
});
return arrayList;
}
添加token认证就是对于webservice添加soapheader头信息。网上最简单的方法是找到webservice引用的具体方法,在具体方法头部加入特性:
[SoapHeader("RequestSOAPHeader")]
由于之前自己很多客户端使用的webservice是使用VS添加服务引用的方式自动生成REFERENCE类,这样写起来不方便,根据实际情况使用了WCF消息拦截器来实现。
GetCommon()方法会返回需要的webservice类,在实例化之后向webservice添加一个拦截器对象,成员变量为token信息。在每次调用此实例化对象时都会通过拦截器方法,将token信息封装到System.ServiceModel.Channels.MessageHeader中,服务端收到的soapheader便是具有token信息的内容。
#region 为客户端添加wcf消息拦截器,用来添加soapheader验证
private class ClientMessageInspector : IClientMessageInspector, System.ServiceModel.Description.IEndpointBehavior
{
public string HeaderValue { get; set; }
#region Implementation for IClientMessageInspector
public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
//MessageBuffer buffer = reply.CreateBufferedCopy(Int32.MaxValue);
//reply = buffer.CreateMessage();
//Message m = buffer.CreateMessage();
//XElement fbEdition = null;
//fbEdition = m.GetBody<XElement>();
//Console.WriteLine(m);
}
public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
{
//XElement fbEdition = null;
//Console.WriteLine(fbEdition = request.GetBody<XElement>());
////Console.WriteLine(fbEdition = request.GetBodyAttribute("findEdition", "http://webService.bhne/"));
request.Headers.Add(System.ServiceModel.Channels.MessageHeader.CreateHeader("token", "http://webService.bhne/", HeaderValue));
return null;
}
#endregion
#region Implementation for IEndpointBehavior
//==================================
public void AddBindingParameters(System.ServiceModel.Description.ServiceEndpoint serviceEndpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters) { }
public void ApplyClientBehavior(System.ServiceModel.Description.ServiceEndpoint serviceEndpoint, ClientRuntime behavior)
{
//此处为Extension附加到ClientRuntime。
behavior.MessageInspectors.Add(this);
}
public void ApplyDispatchBehavior(System.ServiceModel.Description.ServiceEndpoint serviceEndpoint, EndpointDispatcher endpointDispatcher)
{
//如果是扩展服务器端的MessageInspector,则要附加到EndpointDispacther上了。
//endpointDispatcher.DispatchRuntime.MessageInspectors.Add(this);
}
public void Validate(System.ServiceModel.Description.ServiceEndpoint serviceEndpoint) { }
#endregion
}
#endregion
注册拦截器:
//添加头信息
CXFBServiceClient.Endpoint.EndpointBehaviors.Add(new ClientMessageInspector() { HeaderValue = md5_32.ToString() });
此方法目前传递为string字段,实体类型传递未实现。