我需要使用一个wsse:Security节点将这个SOAP流量发送到远程服务,该节点应该看起来像这样:
<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-5FJPET4ATPQZMREXU8C51DK9P6OTW022">
<wsse:Username>NotQuiteThatStupid</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">DonTBotherReadingThisNode</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
我已经尝试使用WCF来完成此任务,因为它看起来像当前的标准,并且文档齐全。长话短说,我找不到使它起作用的方法。
我发挥了作用,从http://blog.aggregatedintelligence.com/2010/06/wcf-transportwithmessagecredential-and.html中汲取了灵感,并将XML节点直接写入标头中:
Dim z_bieTextBinding As TextMessageEncodingBindingElement = New TextMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8)
Dim z_bieHttpBinding As HttpTransportBindingElement = New HttpTransportBindingElement()
Dim z_cbiBinding As CustomBinding = New CustomBinding(z_bieTextBinding, z_bieHttpBinding)
Dim z_epaFinalAddress As EndpointAddress = New EndpointAddress("http://some.where.over/the/rainbow")
Dim z_chfChannels As ChannelFactory(Of IRequestChannel) = New ChannelFactory(Of IRequestChannel)(z_cbiBinding, z_epaFinalAddress)
Dim z_rqcChannel As IRequestChannel = z_chfChannels.CreateChannel()
z_rqcChannel.Open()
Dim z_msgToSend As Message = Message.CreateMessage(MessageVersion.Soap11, p_strActionName, p_objMessageBody)
Dim z_strUserHeader As String = "<wsse:UsernameToken " & _
"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"" " & _
"wsu:Id=""UsernameToken-5FJPET4ATPQZMREXU8C51DK9P6OTW022"">" & _
"<wsse:Username>NoOneYaKnowPardner</wsse:Username>" & _
"<wsse:Password Type=""http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText"">DonTBotherPal</wsse:Password>" & _
"</wsse:UsernameToken>"
Dim z_xdoDocUserHeader As XmlDocument = New XmlDocument()
z_xdoDocUserHeader.LoadXml(z_strUserHeader)
Dim z_mheSecurityHeader As MessageHeader = MessageHeader.CreateHeader("Security", _
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", _
z_xdoDocUserHeader.DocumentElement)
z_msgToSend.Headers.Add(z_mheSecurityHeader)
它确实起作用。 (xmlns属性与模型有些不同,但是它们仍然可以通过。)尽管如此,我仍然不能摆脱不依靠XML操作就应该可行的感觉。因此:
编辑:我尝试了另一种方法。我这样在Web.config中设置了绑定和端点:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="bndSimpleGeneric"
messageEncoding="Text"/>
</basicHttpBinding>
</bindings>
<client>
<endpoint name="enpBasicEndpoint"
address="http://dms-uat.athoris.net/Athoris"
binding="basicHttpBinding"
bindingConfiguration="bndSimpleGeneric"
contract="System.ServiceModel.Channels.IRequestChannel">
<headers>
<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>
<wsse:Username>CanTRememberWho</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">SomethingSomethingOrangesSomething</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</headers>
</endpoint>
</client>
</system.serviceModel>
让我有更简单的代码:
Dim z_chfChannels As New ChannelFactory(Of IRequestChannel)("enpBasicEndpoint")
Dim z_rqcChannel As IRequestChannel = z_chfChannels.CreateChannel()
z_rqcChannel.Open()
Dim z_msgToSend As Message = Message.CreateMessage(MessageVersion.Soap11, "Action Name", "<MessageBody>Words</MessageBody>")
Dim z_mbuToSend As MessageBuffer = z_msgToSend.CreateBufferedCopy(Integer.MaxValue)
Dim z_msgResponse As Message = z_rqcChannel.Request(z_mbuToSend.CreateMessage())
z_rqcChannel.Close()
z_chfChannels.Close()
Return z_msgResponse
如下面的注释所示,我不确定我是否应该对此感到满意,因为用户名(更糟糕的是密码)在Web.config中。不过,对我来说,它看起来比将XML代码与字符串组合在一起要好得多。和以前一样,欢迎对此事发表意见。