2014-11-06 46 views
0

我將linqpad的一個示例代碼的快速部分放在一起,顯示了WCF Web服務調用而未從WSDL創建代理類。這是我有:Win32Exception:使用WebClient調用WCF服務時,目標主體名稱不正確

using (var wb = new WebClient()) 
{ 
    wb.Credentials = CredentialCache.DefaultNetworkCredentials; 
    wb.Headers.Add("Content-Type: text/xml;charset=UTF-8"); 
    wb.Headers.Add("SOAPAction: \"http://tempuri.org/Core/Project_GetNumberForExternalUse\""); 

    String requestString = @" 
    <soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:tem=""http://tempuri.org/""> 
    <soapenv:Header/> 
    <soapenv:Body> 
     <tem:Project_GetNumberForExternalUse> 
      <!--Optional:--> 
      <tem:extData1>ext 1</tem:extData1> 
      <!--Optional:--> 
      <tem:extData2>ext 2</tem:extData2> 
      <!--Optional:--> 
      <tem:extData3>ext 3</tem:extData3> 
      <!--Optional:--> 
      <tem:extData4>ext 4</tem:extData4> 
      <!--Optional:--> 
      <tem:extDataLong>ext 1ext 1ext 1ext 1ext 1</tem:extDataLong> 
     </tem:Project_GetNumberForExternalUse> 
    </soapenv:Body> 
    </soapenv:Envelope> 
    "; 

    var response = wb.UploadString("http://myserver:55002/Core.svc", "POST", requestString); 
    response.Dump(); 
} 

這適用於連接到localhost,但不是myserver。 WCF服務被配置爲使用Windows身份驗證。根據錯誤,我猜測問題是服務主體名稱未包含在授權中。如果我使用帶有代理的WCF客戶端,我會用端點/標識配置部分解決這個問題。但是,我沒有看到在代碼中設置此方法。有沒有辦法做到這一點?是否有其他方式來解決這個需求?

回答

0

MSDN網站:

SPN是一個客戶端用於唯一標識服務器上的服務或應用程序實例以進行相互身份驗證的名稱。相互驗證是默認請求的,您可以通過將WebRequest.AuthenticationLevel設置爲MutualAuthRequired來請求它。

當WebRequest需要雙向認證時,目標的SPN必須由客戶端提供。如果您知道SPN,則可以在發送請求之前將其添加到CustomTargetNameDictionary中。如果您尚未將SPN信息添加到此字典中,則AuthenticationManager將使用RequestUri方法組成最可能的SPN;但是,這是一個計算值,可能不正確。如果雙向認證嘗試失敗,則可以檢查字典以確定計算出的SPN。如果身份驗證協議不支持相互身份驗證,則不會將SPN輸入字典。

所以加入Authentication.CutomTargetNameDictionary的URL和spn,應該可以解決你的問題。

using (var wb = new WebClient()) 
{ 
    const string URL = "http://myserver:55002/Core.svc"; 

    wb.Credentials = CredentialCache.DefaultNetworkCredentials; 
    wb.Headers.Add("Content-Type: text/xml;charset=UTF-8"); 
    wb.Headers.Add("SOAPAction: \"http://tempuri.org/Core/Project_GetNumberForExternalUse\""); 

    String requestString = @" 
    <soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:tem=""http://tempuri.org/""> 
    <soapenv:Header/> 
    <soapenv:Body> 
     <tem:Project_GetNumberForExternalUse> 
      <!--Optional:--> 
      <tem:extData1>ext 1</tem:extData1> 
      <!--Optional:--> 
      <tem:extData2>ext 2</tem:extData2> 
      <!--Optional:--> 
      <tem:extData3>ext 3</tem:extData3> 
      <!--Optional:--> 
      <tem:extData4>ext 4</tem:extData4> 
      <!--Optional:--> 
      <tem:extDataLong>ext 1ext 1ext 1ext 1ext 1</tem:extDataLong> 
     </tem:Project_GetNumberForExternalUse> 
    </soapenv:Body> 
    </soapenv:Envelope> 
    "; 

    var uri = new Uri(URL); 
    var spn = $"{uri.Scheme}/{uri.Authority}"; 
    AuthenticationManager.CustomTargetNameDictionary.Add(URL, spn); 

    var response = wb.UploadString(URL, "POST", requestString); 
    response.Dump(); 
} 
相關問題