背景
我工作的公司有一个通过WCF向网络公开的产品,特别是通过一个包含处理所有消息的单一方法的服务合同。在内部,产品解析SOAP标头和正文,加载服务插件,并将请求路由到该插件。
我已经编写了其中一个插件来托管PowerShell运行时,并提供了一个挂钩到该产品的某些内部管道的自定义主机。远程客户端可以向服务器发送任意脚本以执行,包括利用产品本身的功能。
要明确:我很清楚安全隐患。此插件仅用于诊断和原型设计,不适用于生产用途或部署。
问题:
在作为回复发回的数据合同中,我传递了一组PSObject
个实例:
[DataContractAttribute]
public partial class RunScriptResponse
{
[DataMember]
public PSObject[] Output { get; set; }
}
根据this article,应支持PSObject
;它实现ISerializable
并拥有SerializableAttribute
。
响应数据合同正在由服务器进行序列化,并且正在被客户端无故接收 - 正如WCF可扩展性点所验证的那样。但是,当服务客户端尝试反序列化对象时,我点击了[1]:
Member 'CliXml' was not found.
然而,看看响应XML,它非常清楚,那个成员就在那里:
<RunScriptResponse xmlns="...">
<RunScriptResult xmlns:d1p1="..." xmlns:e="..." xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<e:Output xmlns:d1p1="http://schemas.datacontract.org/2004/07/System.Management.Automation">
<d1p1:PSObject>
<CliXml i:type="d3p1:string" xmlns:d3p1="http://www.w3.org/2001/XMLSchema">
<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">
它表明在反序列化过程中发生某事,PSObject
无法找到<CliXml>
元素,但我无法弄清楚为什么
此外,尝试访问此服务器的特定客户端本身就是PowerShell模块,通过反射从代理程序集动态生成。目的是您可以将脚本传递给服务器,返回一些PSObject
实例,并在客户端上进行进一步处理。
鉴于其自动生成的性质,无法切换到其他序列化方案,例如序列化服务器上的PSObject
实例,传递字符串数组,然后在其上反序列化它们客户。这将需要独特的一对一方法处理,这将使模块生成过程显着复杂化。
有没有人对如何进一步解决此问题或其他策略有任何建议?
谢谢!
[1]异常的堆栈跟踪:
at System.Runtime.Serialization.SerializationInfo.GetElement(String name, Type& foundType)
at System.Runtime.Serialization.SerializationInfo.GetValue(String name, Type type)
at System.Management.Automation.PSObject..ctor(SerializationInfo info, StreamingContext context)
at ReadPSObjectFromXml(XmlReaderDelegator , XmlObjectSerializerReadContext , XmlDictionaryString[] , XmlDictionaryString[] )
at System.Runtime.Serialization.ClassDataContract.ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context)
at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator reader, String name, String ns, Type declaredType, DataContract& dataContract)
at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator xmlReader, Int32 id, RuntimeTypeHandle declaredTypeHandle, String name, String ns)
at ReadArrayOfPSObjectFromXml(XmlReaderDelegator , XmlObjectSerializerReadContext , XmlDictionaryString , XmlDictionaryString , CollectionDataContract )
at System.Runtime.Serialization.CollectionDataContract.ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context)
at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator reader, String name, String ns, Type declaredType, DataContract& dataContract)
at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator xmlReader, Int32 id, RuntimeTypeHandle declaredTypeHandle, String name, String ns)
at ReadRunScriptResponseFromXml(XmlReaderDelegator , XmlObjectSerializerReadContext , XmlDictionaryString[] , XmlDictionaryString[] )
at System.Runtime.Serialization.ClassDataContract.ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context)
at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator reader, String name, String ns, Type declaredType, DataContract& dataContract)
at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator xmlReader, Type declaredType, DataContract dataContract, String name, String ns)
at System.Runtime.Serialization.DataContractSerializer.InternalReadObject(XmlReaderDelegator xmlReader, Boolean verifyObjectName, DataContractResolver dataContractResolver)
at System.Runtime.Serialization.XmlObjectSerializer.ReadObjectHandleExceptions(XmlReaderDelegator reader, Boolean verifyObjectName, DataContractResolver dataContractResolver)
at System.Runtime.Serialization.DataContractSerializer.ReadObject(XmlDictionaryReader reader, Boolean verifyObjectName)
at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.PartInfo.ReadObject(XmlDictionaryReader reader, XmlObjectSerializer serializer)
at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.DeserializeParameterPart(XmlDictionaryReader reader, PartInfo part, Boolean isRequest)
20180129:我在客户端使用的代码是普通的WCF。我通过svcutil.exe
从服务接口程序集导出WSDL和XSD,然后通过svcutil.exe
运行它们以生成C#代理。从那里,一切都只是按原样调用代理:
// Utility code that wraps the programmatic generation of a proxy.
// Manually instantiates `WSHttpBinding` and `EndpointAddress`, then
// constructs an instance of the proxy client using those two objects.
//
var client = GenerateProxyClient<RunScriptRequest,
IScriptingService,
ScriptingServiceClient,
RunScriptResponse>();
var response = client.RunScript(new RunScriptRequest
{
Script = @"Get-ChildItem C:\"
});