使用WCF进行POX REST调用时的双重请求,并将WebHttpBinding设置为“基本身份验证”

时间:2009-09-22 19:57:44

标签: xml wcf rest tcptrace-pocketsoap

使用WCF进行POX REST调用时出现问题,并将WebHttpBinding设置为基本身份验证(HttpClientCredentialType.Basic)

而不是来自客户端的一个调用,在HTTP Header中指定了“Authorization:Basic”,而是进行了两次调用。首先调用没有身份验证到哪些服务响应有401 Unauthorized错误,第二次调用带有正确的身份验证信息。

这似乎是由WCF服务处理的,根本没有打嗝。调用第三方服务显然会产生问题,因为它们会立即响应错误。

服务代码:

[ServiceContract]
public interface IService
{
    [OperationContract]
    [WebInvoke(BodyStyle = WebMessageBodyStyle.Bare,
        RequestFormat = WebMessageFormat.Xml,
        UriTemplate = "")]
    Message SendData(Message message);

}

public class Service : IService
{
    public Message SendData(Message message)
    {           return Message.CreateMessage(MessageVersion.None, String.Empty, "test");
    }
}

客户代码:

public class Client: WebChannelFactory<IService>, IService
{
    public Client(Uri baseUri, string userName, string password)
        : base(CreateBinding(),
               baseUri)
    {
        Credentials.UserName.UserName = userName;
        Credentials.UserName.Password = password;
    }

    public Message SendData(Message requestMessage)
    {
        var channel = CreateChannel();
        Message responseMessage = channel.SendData(requestMessage);
        return responseMessage;
    }

    private static Binding CreateBinding()
    {
        var binding = new WebHttpBinding();
        binding.Security.Mode = WebHttpSecurityMode.TransportCredentialOnly;
        binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
        return binding;
    }

}

使用TcpTrace我看到这些请求背靠背:

POST / HTTP/1.1  
Content-Type: application/xml; charset=utf-8  
VsDebuggerCausalityData:   uIDPo2lH6p+lUOdFmrqDKGWYeQkAAAAA7+Y4QR6wNUWZmwCaasMx7xrfcJZxph9NocstwCh8NQsACQAA  
Host: localhost:9090  
Content-Length: 89  
Expect: 100-continue  
Connection: Keep-Alive  

<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">test request</string>  

POST / HTTP/1.1  
Content-Type: application/xml; charset=utf-8  
VsDebuggerCausalityData: uIDPo2lH6p+lUOdFmrqDKGWYeQkAAAAA7+Y4QR6wNUWZmwCaasMx7xrfcJZxph9NocstwCh8NQsACQAA  
Authorization: Basic dGVzdDp0ZXN0  
Host: localhost:9090  
Content-Length: 89  
Expect: 100-continue  

<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">test request</string> 

注意只有第二个电话包含:授权:基本dGVzdDp0ZXN0 如何停止第一个请求(未经授权)?

使用TcpTrace实用程序的示例解决方案可以在此处下载:

WCF-BasicAuthenticationIssue.zip

2 个答案:

答案 0 :(得分:4)

基于Remus的回答,这是我的解决方法

        public Message SendData(Message requestMessage)
    {
        var channel = CreateChannel();
        Message responseMessage;
        using (new OperationContextScope((IClientChannel)channel))
        {
            WebOperationContext.Current.OutgoingRequest
                .Headers[HttpRequestHeader.Authorization] = "Basic "
                + Convert.ToBase64String(Encoding.ASCII.GetBytes(
                Credentials.UserName.UserName + ":" + Credentials.UserName.Password));
            responseMessage = channel.SendData(requestMessage); 
        }
        return responseMessage;
    }

我只是强迫第一次请求出去使用基本授权

答案 1 :(得分:3)

问题实际上在于那些第三方。每RFC 2617基本身份验证在两次调用中完成,就像Digest一样。服务器应在第一次呼叫时使用包含领域的挑战进行响应:

  

收到未经授权的人   请求中的URI   保护空间,原始服务器   可以回应像锡这样的挑战   以下内容:

  WWW-Authenticate: Basic realm="WallyWorld"
     

其中“WallyWorld”是字符串   由服务器分配以识别
  保护空间   请求URI

WCF端点将在第一个之后仅对后续调用进行预身份验证。应用程序域对任何资源的第一次调用将不包含基本标头用户名和密码。

另见What happened to the PreAuthenticate flag in WCF