簡體   English   中英

每個請求的C#WebClient NTLM身份驗證啟動

[英]C# WebClient NTLM authentication starting for each request

考慮一個簡單的C#.NET Framework 4.0應用程序,它:

  • 使用WebClient
  • 使用NTLM進行身份驗證(在IIS 6.0和IIS 7.5服務器上測試)
  • 使用DownloadString()多次從URL檢索字符串

這是一個工作正常的樣本:

using System;
using System.Net;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string URL_status = "http://localhost/status";

            CredentialCache myCache = new CredentialCache();
            myCache.Add(new Uri(URL_status), "NTLM", new NetworkCredential("username", "password", "domain"));

            WebClient WebClient = new WebClient();
            WebClient.Credentials = myCache;

            for (int i = 1; i <= 5; i++)
            {
                string Result = WebClient.DownloadString(new Uri(URL_status));
                Console.WriteLine("Try " + i.ToString() + ": " + Result);
            }

            Console.Write("Done");
            Console.ReadKey();
        }
    }
}

問題:

啟用跟蹤時,我發現NTLM身份驗證不會持久存在。

每次調用Webclient.DownloadString時,NTLM身份驗證都會啟動(服務器返回“WWW-Authenticate:NTLM”標頭,並且整個身份驗證/授權過程重復;沒有“Connection:close”標頭)。

是不是NTLM應該驗證連接,而不是請求?

有沒有辦法讓WebClient重用現有連接以避免重新驗證每個請求?

經過10天嘗試我能想到的一切並在此過程中學到很多東西,我終於找到了解決這個問題的方法。

訣竅是通過重寫GetWebRequest並在您返回的HttpWebRequest中將屬性設置為true來啟用UnsafeAuthenticatedConnectionSharing

您可能希望將其與ConnectionGroupName屬性組合,以避免未經身份驗證的應用程序對連接的潛在使用。

以下是修改后的問題樣本按預期工作。 它打開一個NTLM身份驗證連接並重用它:

using System;
using System.Net;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string URL_status = "http://localhost/status";

            CredentialCache myCache = new CredentialCache();
            myCache.Add(new Uri(URL_status), "NTLM", new NetworkCredential("username", "password", "domain"));

            MyWebClient webClient = new MyWebClient();
            webClient.Credentials = myCache;

            for (int i = 1; i <= 5; i++)
            {
                string result = webClient.DownloadString(new Uri(URL_status));
                Console.WriteLine("Try {0}: {1}", i, result);
            }

            Console.Write("Done");
            Console.ReadKey();
        }
    }

    public class MyWebClient : WebClient
    {
        protected override WebRequest GetWebRequest(Uri address)
        {
            WebRequest request = base.GetWebRequest(address);

            if (request is HttpWebRequest) 
            {
                var myWebRequest = request as HttpWebRequest;
                myWebRequest.UnsafeAuthenticatedConnectionSharing = true;
                myWebRequest.KeepAlive = true;
            }

            return request;
        }
    }   
}

在這一點上,我還要感謝@Falco Alexander的所有幫助; 雖然他的建議對我不起作用,但他確實指出了我正確的方向尋找並最終找到答案。

檢查IIS的設置,但這應該是默認設置。

<windowsAuthentication
   enabled="True"
   authPersistSingleRequest="False"
   UseKernelMode>

</windowsAuthentication>  

參考: https//msdn.microsoft.com/en-us/library/aa347472.aspx

您是否檢查了localhost IIS所在的區域? 在使用WinInet時,這也是客戶端的一個陷阱。 檢查WebClient默認行為。


編輯:

在重現錯誤之后,我可以發現它是WebClient缺少的NTLM 預身份驗證實現,它使您免於單個401請求:

var WebClient = new PreAuthWebClient();
WebClient.Credentials = new NetworkCredential("user", "pass","domain");

//Do your GETs 

Public class PreAuthWebClient: WebClient
{
    protected override WebRequest GetWebRequest (Uri address)
    {
        WebRequest request = (WebRequest) base.GetWebRequest (address);
        request.PreAuthenticate = true;
        return request;
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM