BasicHttpBinding 相当于使用 WCF 客户端和 PHP WebService 的 CustomBinding
我正在使用 WCF 运行带有 WebService PHP 的 Visual Studio 2008 单元测试 C#,并收到以下错误:
System.ServiceModel.Security.MessageSecurityException: HTTP 请求未经授权 客户端认证方案 '匿名的'。身份验证标头 从服务器收到的是 'NTLM,基本领域=“(空)”'。 ---> System.Net.WebException:远程 服务器返回错误:(401) 未经授权..
我使用 Windows XP SP3 机器,单元测试 VS 2008 和 WCF 连接到 PHP WebService。
我无法控制 PHP WebService。我无法修改它(配置安全性也无法修改)。
这是我使用 Web 服务 PHP 的客户端的配置文件:
<system.serviceModel>
<extensions>
<bindingElementExtensions>
<add name="customTextMessageEncoding"
type="COMPANY.IntegracionEasyVista.CustomTextEncoder.CustomTextMessageEncodingElement,COMPANY.IntegracionEasyVista.CustomTextEncoder, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9744987c0853bf9e" />
</bindingElementExtensions>
</extensions>
<bindings>
<customBinding>
<binding name="ISO8859Binding">
<customTextMessageEncoding messageVersion="Soap11WSAddressing10"
encoding="ISO-8859-1" />
<httpTransport />
</binding>
</customBinding>
</bindings>
<client>
<endpoint address="http://serverphp/webservice/SmoBridge.php"
binding="customBinding" bindingConfiguration="ISO8859Binding"
contract="ServiceEasyVista.WebServicePortType" name="EasyVistaSvcEndPoint" />
</client>
</system.serviceModel>
实际上,我使用 C# 代码:
var endpointAddress = Config.AppSettings.Settings[EasyVistaSvcEndPointAddress].Value;
var endpoint = new System.ServiceModel.EndpointAddress(endpointAddress);
var endpointBinding = new System.ServiceModel.Channels.CustomBinding();
endpointBinding.Name = "ISO8859Binding";
var bindingElement = new IntegracionEasyVista.CustomTextEncoder.CustomTextMessageBindingElement();
bindingElement.Encoding = "ISO-8859-1";
bindingElement.MessageVersion = System.ServiceModel.Channels.MessageVersion.Soap11WSAddressing10; // "Soap11WSAddressing10"
endpointBinding.Elements.Add(bindingElement);
var transportBinding = new HttpTransportBindingElement();
endpointBinding.Elements.Add(transportBinding);
ConfigurarBinding(endpointBinding);
var svcClient = new WebServicePortTypeClient(endpointBinding, endpoint);
return svcClient;
更新:测试
我添加此行:
transportBinding.AuthenticationScheme = System.Net.AuthenticationSchemes.Negotiate;
我收到此错误: HTTP 请求未经客户端身份验证方案“匿名”的授权。从服务器收到的身份验证标头是“NTLM,基本领域=”(空)“”
我添加此行:
transportBinding.AuthenticationScheme = System.Net.AuthenticationSchemes.Basic;
我收到此错误:
System.ServiceModel.CommunicationObjectFaultedException: El object de comunicación, 系统.ServiceModel.Channels.ServiceChannel, 请不要使用通讯工具 进入国家时 出错了。
//服务器堆栈跟踪: // en System.ServiceModel.Channels.CommunicationObject.Close(TimeSpan 超时)
我添加这一行:
transportBinding.AuthenticationScheme = System.Net.AuthenticationSchemes.Ntlm;
我收到此错误:
/异常= System.ServiceModel.CommunicationException: 版本 de mensaje no reconocida。
//服务器堆栈跟踪: // en System.ServiceModel.Channels.ReceivedMessage.ReadStartEnvelope(XmlDictionaryReader) 读者)
// zh System.ServiceModel.Channels.StreamedMessage..ctor(XmlDictionaryReader 读取器,Int32 maxSizeOfHeaders, 消息版本(desiredVersion)
// zh System.ServiceModel.Channels.Message.CreateMessage(XmlDictionaryReader) 信封读取器,Int32 标头最大大小、消息版本 版本)
// zh System.ServiceModel.Channels.Message.CreateMessage(XmlReader 信封读取器,Int32 标头最大大小、消息版本 版本)
// zh CustomTextEncoder.CustomTextMessageEncoder.ReadMessage(流 流,Int32 maxSizeOfHeaders,字符串 内容类型) en E:\TFS\pro\CustomTextEncoder\CustomTextMessageEncoder.cs:linea 66
// zh System.ServiceModel.Channels.MessageEncoder.ReadMessage(流 流,Int32 maxSizeOfHeaders)
// zh CustomTextEncoder.CustomTextMessageEncoder.ReadMessage (ArraySegment`1 缓冲区,BufferManager bufferManager, 字符串 contentType) zh E:\TFS\pro\CustomTextEncoder\CustomTextMessageEncoder.cs:linea 60
// zh System.ServiceModel.Channels.MessageEncoder.ReadMessage(流 流,BufferManager 缓冲区管理器, Int32 最大缓冲区大小,字符串 内容类型)
// zh System.ServiceModel.Channels.HttpInput.ReadChunkedBufferedMessage(流 输入流)
我认为,以下是正确的配置(如果是basichttpbinding)
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Basic" />
</security>
basichttpbinding中的WCF Web服务可能不够灵活。 CustomBinding 顾名思义,它允许用户设计自己的 Web 服务绑定。
我需要使用 CustomBinding 和 SecurityMode (如 basichttpbinding): WCF BasicHttpBinding 等效 CustomBinding
我需要安全模式: TransportCredentialOnly、Basic、HTTP 传输和编码 =“ISO-8859-1”
http://www.codemeit.com/security/wcf-basichttpbinding-equivalent-custombinding.html
http://social.msdn。 microsoft.com/Forums/en/wcf/thread/6cefadf1-9939-4f3b-a502-2d79a30c7d3a
http://offroadcoder.com/2008/03/23/CallingYourNusoapPHPWebServiceFromWCF.aspx
http://msdn.microsoft.com/en-us/library/ms731092(v=VS.90).aspx
我再次尝试使用此配置,我收到错误:
svcPro.ClientCredentials.UserName.UserName = "MY USER";
svcPro.ClientCredentials.UserName.Password = "XXXX";
配置:
<customBinding>
<binding name="ISO8859Binding">
<customTextMessageEncoding messageVersion="Soap11WSAddressing10" encoding="ISO-8859-1" />
<!--<textMessageEncoding MessageVersion="Soap11" />-->
<!--<httpTransport />-->
<httpTransport authenticationScheme="Basic" />
</binding>
</customBinding>
错误(InnerException 为空):
错误:无法识别的消息版本
提示: System.ServiceModel.CommunicationException Mensaje: 没有 Mensaje 的版本 杀戮。 StackTrace:服务器堆栈 跟踪:
zh System.ServiceModel.Channels.ReceivedMessage.ReadStartEnvelope(XmlDictionaryReader) 读者)
zh System.ServiceModel.Channels.StreamedMessage..ctor(XmlDictionaryReader 读取器,Int32 maxSizeOfHeaders, 消息版本(desiredVersion)
zh System.ServiceModel.Channels.Message.CreateMessage(XmlDictionaryReader) 信封读取器,Int32 标头最大大小、消息版本 版本)
zh System.ServiceModel.Channels.Message.CreateMessage(XmlReader 信封读取器,Int32 标头最大大小、消息版本 版本)
zh Reale.IntegracionEasyVista.CustomTextEncoder.CustomTextMessageEncoder.ReadMessage(Stream 流,Int32 maxSizeOfHeaders,字符串 内容类型) en E:\IntegracionEasyVista\CustomTextEncoder\CustomTextMessageEncoder.cs:linea 66
zh System.ServiceModel.Channels.MessageEncoder.ReadMessage(流 流,Int32 maxSizeOfHeaders) zh Reale.IntegracionEasyVista.CustomTextEncoder.CustomTextMessageEncoder.ReadMessage(ArraySegment`1 缓冲区, BufferManager 缓冲区管理器, 字符串 contentType) zh E:\IntegracionEasyVista\CustomTextEncoder\CustomTextMessageEncoder.cs:linea 60
zh System.ServiceModel.Channels.MessageEncoder.ReadMessage(流 流,BufferManager 缓冲区管理器, Int32 最大缓冲区大小,字符串 内容类型)
zh System.ServiceModel.Channels.HttpInput.ReadChunkedBufferedMessage(流 输入流)
zh System.ServiceModel.Channels.HttpInput.ParseIncomingMessage(异常& 请求异常)
zh System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(时间跨度 超时)
zh System.ServiceModel.Channels.RequestChannel.Request(消息 消息、TimeSpan 超时)
zh System.ServiceModel.Dispatcher.RequestChannelBinder.Request(消息 消息、TimeSpan 超时)
zh System.ServiceModel.Channels.ServiceChannel.Call(字符串 动作,布尔单向, ProxyOperation运行时操作, 对象 [] 输入、对象 [] 输出、TimeSpan 超时)
zh System.ServiceModel.Channels.ServiceChannel.Call(字符串 动作,布尔单向, ProxyOperation运行时操作, Object[] ins,Object[] outs)
zh System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage 方法调用、代理操作运行时 操作)
zh System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage 消息)
更多信息:Service.php 的 WDSL 的一部分
<?xml version="1.0" encoding="ISO-8859-1" ?>
<definitions
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:si="http://soapinterop.org/xsd"
xmlns:tns="http://192.168.110.50/WebService" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://192.168.110.50/WebService">
<types>
<xsd:schema targetNamespace="http://192.168.110.50/WebService">
<xsd:import namespace="http://schemas.xmlsoap.org/soap/encoding/" />
<xsd:import namespace="http://schemas.xmlsoap.org/wsdl/" />
</xsd:schema>
</types>
I was running my Visual Studio 2008 Unit Test C# with a WebService PHP using WCF and I received the following error:
System.ServiceModel.Security.MessageSecurityException:
The HTTP request is unauthorized with
client authentication scheme
'Anonymous'. The authentication header
received from the server was
'NTLM,Basic realm="(null)"'. --->
System.Net.WebException: The remote
server returned an error: (401)
Unauthorized..
I am using Windows XP SP3 machine, unit test VS 2008 and WCF for connect to PHP WebService.
I have no control about PHP WebService. I cannot modify it (neither configuration security).
Here is my config file for the client that use the webservice PHP:
<system.serviceModel>
<extensions>
<bindingElementExtensions>
<add name="customTextMessageEncoding"
type="COMPANY.IntegracionEasyVista.CustomTextEncoder.CustomTextMessageEncodingElement,COMPANY.IntegracionEasyVista.CustomTextEncoder, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9744987c0853bf9e" />
</bindingElementExtensions>
</extensions>
<bindings>
<customBinding>
<binding name="ISO8859Binding">
<customTextMessageEncoding messageVersion="Soap11WSAddressing10"
encoding="ISO-8859-1" />
<httpTransport />
</binding>
</customBinding>
</bindings>
<client>
<endpoint address="http://serverphp/webservice/SmoBridge.php"
binding="customBinding" bindingConfiguration="ISO8859Binding"
contract="ServiceEasyVista.WebServicePortType" name="EasyVistaSvcEndPoint" />
</client>
</system.serviceModel>
Really, I use C# code:
var endpointAddress = Config.AppSettings.Settings[EasyVistaSvcEndPointAddress].Value;
var endpoint = new System.ServiceModel.EndpointAddress(endpointAddress);
var endpointBinding = new System.ServiceModel.Channels.CustomBinding();
endpointBinding.Name = "ISO8859Binding";
var bindingElement = new IntegracionEasyVista.CustomTextEncoder.CustomTextMessageBindingElement();
bindingElement.Encoding = "ISO-8859-1";
bindingElement.MessageVersion = System.ServiceModel.Channels.MessageVersion.Soap11WSAddressing10; // "Soap11WSAddressing10"
endpointBinding.Elements.Add(bindingElement);
var transportBinding = new HttpTransportBindingElement();
endpointBinding.Elements.Add(transportBinding);
ConfigurarBinding(endpointBinding);
var svcClient = new WebServicePortTypeClient(endpointBinding, endpoint);
return svcClient;
Update: tests
I add this line:
transportBinding.AuthenticationScheme = System.Net.AuthenticationSchemes.Negotiate;
I get this error: The HTTP request is unauthorized with client authentication scheme 'Anonymous'. The authentication header received from the server was 'NTLM,Basic realm="(null)"'
I add this line:
transportBinding.AuthenticationScheme = System.Net.AuthenticationSchemes.Basic;
I get thiserror:
System.ServiceModel.CommunicationObjectFaultedException:
El objeto de comunicación,
System.ServiceModel.Channels.ServiceChannel,
no se puede usar para la comunicación
porque se encuentra en el estado
Faulted.//Server stack trace: // en
System.ServiceModel.Channels.CommunicationObject.Close(TimeSpan
timeout)
I add this line:
transportBinding.AuthenticationScheme = System.Net.AuthenticationSchemes.Ntlm;
I get thiserror:
/Exception =
System.ServiceModel.CommunicationException:
Versión de mensaje no reconocida.//Server stack trace: // en
System.ServiceModel.Channels.ReceivedMessage.ReadStartEnvelope(XmlDictionaryReader
reader)// en
System.ServiceModel.Channels.StreamedMessage..ctor(XmlDictionaryReader
reader, Int32 maxSizeOfHeaders,
MessageVersion desiredVersion)// en
System.ServiceModel.Channels.Message.CreateMessage(XmlDictionaryReader
envelopeReader, Int32
maxSizeOfHeaders, MessageVersion
version)// en
System.ServiceModel.Channels.Message.CreateMessage(XmlReader
envelopeReader, Int32
maxSizeOfHeaders, MessageVersion
version)// en
CustomTextEncoder.CustomTextMessageEncoder.ReadMessage(Stream
stream, Int32 maxSizeOfHeaders, String
contentType) en
E:\TFS\pro\CustomTextEncoder\CustomTextMessageEncoder.cs:línea
66// en
System.ServiceModel.Channels.MessageEncoder.ReadMessage(Stream
stream, Int32 maxSizeOfHeaders)// en
CustomTextEncoder.CustomTextMessageEncoder.ReadMessage
(ArraySegment`1 buffer, BufferManager
bufferManager, String contentType) en
E:\TFS\pro\CustomTextEncoder\CustomTextMessageEncoder.cs:línea
60// en
System.ServiceModel.Channels.MessageEncoder.ReadMessage(Stream
stream, BufferManager bufferManager,
Int32 maxBufferSize, String
contentType)// en
System.ServiceModel.Channels.HttpInput.ReadChunkedBufferedMessage(Stream
inputStream)
I think, the following is right configuration (if were basichttpbinding)
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Basic" />
</security>
Web service of WCF in basichttpbinding might not be flexible enough. CustomBinding as the name describes that it alllows users design their own web service binding.
I need use CustomBinding and SecurityMode (like basichttpbinding): WCF BasicHttpBinding equivalent CustomBinding
I need Security Mode: TransportCredentialOnly, Basic, HTTP transport and encoding="ISO-8859-1"
http://www.codemeit.com/security/wcf-basichttpbinding-equivalent-custombinding.html
http://social.msdn.microsoft.com/Forums/en/wcf/thread/6cefadf1-9939-4f3b-a502-2d79a30c7d3a
http://offroadcoder.com/2008/03/23/CallingYourNusoapPHPWebServiceFromWCF.aspx
http://msdn.microsoft.com/en-us/library/ms731092(v=VS.90).aspx
I try again using this configuration, and I get the error:
svcPro.ClientCredentials.UserName.UserName = "MY USER";
svcPro.ClientCredentials.UserName.Password = "XXXX";
Config:
<customBinding>
<binding name="ISO8859Binding">
<customTextMessageEncoding messageVersion="Soap11WSAddressing10" encoding="ISO-8859-1" />
<!--<textMessageEncoding MessageVersion="Soap11" />-->
<!--<httpTransport />-->
<httpTransport authenticationScheme="Basic" />
</binding>
</customBinding>
The error (InnerException is null):
Error: Unrecognized message version
Tipo:
System.ServiceModel.CommunicationException
Mensaje: Versión de mensaje no
reconocida. StackTrace: Server stack
trace:en
System.ServiceModel.Channels.ReceivedMessage.ReadStartEnvelope(XmlDictionaryReader
reader)en
System.ServiceModel.Channels.StreamedMessage..ctor(XmlDictionaryReader
reader, Int32 maxSizeOfHeaders,
MessageVersion desiredVersion)en
System.ServiceModel.Channels.Message.CreateMessage(XmlDictionaryReader
envelopeReader, Int32
maxSizeOfHeaders, MessageVersion
version)en
System.ServiceModel.Channels.Message.CreateMessage(XmlReader
envelopeReader, Int32
maxSizeOfHeaders, MessageVersion
version)en
Reale.IntegracionEasyVista.CustomTextEncoder.CustomTextMessageEncoder.ReadMessage(Stream
stream, Int32 maxSizeOfHeaders, String
contentType) en
E:\IntegracionEasyVista\CustomTextEncoder\CustomTextMessageEncoder.cs:línea
66en
System.ServiceModel.Channels.MessageEncoder.ReadMessage(Stream
stream, Int32 maxSizeOfHeaders)
en Reale.IntegracionEasyVista.CustomTextEncoder.CustomTextMessageEncoder.ReadMessage(ArraySegment`1
buffer, BufferManager bufferManager,
String contentType) en
E:\IntegracionEasyVista\CustomTextEncoder\CustomTextMessageEncoder.cs:línea
60en
System.ServiceModel.Channels.MessageEncoder.ReadMessage(Stream
stream, BufferManager bufferManager,
Int32 maxBufferSize, String
contentType)en
System.ServiceModel.Channels.HttpInput.ReadChunkedBufferedMessage(Stream
inputStream)en
System.ServiceModel.Channels.HttpInput.ParseIncomingMessage(Exception&
requestException)en
System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan
timeout)en
System.ServiceModel.Channels.RequestChannel.Request(Message
message, TimeSpan timeout)en
System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message
message, TimeSpan timeout)en
System.ServiceModel.Channels.ServiceChannel.Call(String
action, Boolean oneway,
ProxyOperationRuntime operation,
Object[] ins, Object[] outs, TimeSpan
timeout)en
System.ServiceModel.Channels.ServiceChannel.Call(String
action, Boolean oneway,
ProxyOperationRuntime operation,
Object[] ins, Object[] outs)en
System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage
methodCall, ProxyOperationRuntime
operation)en
System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage
message)
More info: part of WDSL of Service.php
<?xml version="1.0" encoding="ISO-8859-1" ?>
<definitions
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:si="http://soapinterop.org/xsd"
xmlns:tns="http://192.168.110.50/WebService" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://192.168.110.50/WebService">
<types>
<xsd:schema targetNamespace="http://192.168.110.50/WebService">
<xsd:import namespace="http://schemas.xmlsoap.org/soap/encoding/" />
<xsd:import namespace="http://schemas.xmlsoap.org/wsdl/" />
</xsd:schema>
</types>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您的 PHP 服务需要身份验证,但您的客户端不发送任何身份验证。更改您的自定义绑定以支持身份验证。您可以在 httpTransport 元素中设置身份验证:
使用基本或协商。 Basic 将要求您在与服务通信时提供客户端凭据。协商将要求服务和客户端位于同一域中。
Your PHP service requires authentication but your client doesn't send any. Change your custom binding to support authentication. You can set authentication in httpTransport element:
Use Basic or Negotiate. Basic will require you to provide client credentials when communicating with the service. Negotiate will require that both service and client are in the same domain.