2009-09-22 22 views
2

有一個問題,同時使利用WCF與的WebHttpBinding設置爲基本身份驗證(HttpClientCredentialType.Basic)從客戶雙重要求,同時使利用WCF與POX的WebHttpBinding REST調用設置爲基本身份驗證

而不是一個呼叫POX REST調用在HTTP標題中指定「授權:基本」時,將進行兩個調用。首先不進行身份驗證的呼叫,以及401未授權錯誤的服務響應,第二次呼叫具有適當的身份驗證信息。

這似乎是由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

回答

3

實際上,問題在於這些第三方。每RFC 2617基本身份驗證在兩次調用中完成,就像Digest一樣。服務器應該包含一個領域是一個挑戰第一響應號召:

在收到
保護空間內的未授權 請求URI的,原始服務器 可以用相同的
應對挑戰以下:

WWW-Authenticate: Basic realm="WallyWorld" 

其中「WallyWorld」是由服務器分配,以確定
012的保護空間字符串的Request-URI

的WCF端點將預認證只後的第一個後續電話。 appdomain對任何資源所做的第一次調用將不包含基本的頭用戶名和密碼。請參閱What happened to the PreAuthenticate flag in WCF

+0

拉莫斯, 非常感謝你爲你解答。這很明顯。 – 2009-09-22 21:59:01

+0

你說_Basic認證是在兩個call_中完成的,但不應該說_Asas認證**可以在兩個call_中完成**,因爲RFC 2617沒有明確說第一個請求不能包含憑證。 – 2017-12-15 03:58:56

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; 
    } 

我只是迫使第一次請求走出去與基本授權

+0

Yeap,這就是大家都在做的,手動添加標題。 – 2009-09-22 22:33:09

+0

感謝Jakub,您的代碼完美地調用了WCF REST服務,並使用WcfRestContrib實現了自定義基本身份驗證。 – 2012-05-24 18:36:47