首页 > 解决方案 > 什么是 NTLM/身份验证/协商 Web 身份验证

问题描述

我了解基本身份验证和摘要身份验证。但我搜索了很多,我在 NTLM、Authenticate 和 Negotiate 方面苦苦挣扎。

我认为,如果我错了,请纠正我,NTLM 和 Authenticate 是同一协议的两个术语。

协商首先尝试 NTLM,然后回退到消化,然后回退到基本连接。

那是对的吗?如果是这样,哪里是一个很好的例子,说明如何在 C# 中连接仅用于 NTLM 和协商。

我有两个用例。首先是我需要拉下一个文件。所以发出一个请求,得到一个 XML 文件作为响应,读下来,完成。

第二个是查询 OData,因此有数百到数千个 Web 请求,每个请求都将提供 JSON(或 XML)作为响应。

标签: c#httpwebrequestntlmhttp-authenticationhttp-negotiate

解决方案


Microsoft Negotiate 是一个安全支持提供程序 (SSP),它充当安全支持提供程序接口 (SSPI) 和其他 SSP 之间的应用层。当应用程序调用 SSPI 登录网络时,它可以指定一个 SSP 来处理请求。如果应用程序指定 Negotiate,Negotiate 会分析请求并根据客户配置的安全策略选择最佳 SSP 来处理请求。

https://docs.microsoft.com/en-us/windows/desktop/secauthn/microsoft-negotiate

正如文章 Negotiate 中给出的那样,并没有回退到消化。Negotiate 在某种程度上类似于 Kerberos,但具有 NTLM 的默认备份

目前,协商安全包在 Kerberos 和 NTLM 之间进行选择。Negotiate 选择 Kerberos,除非它不能被参与身份验证的系统之一使用,或者调用应用程序没有提供足够的信息来使用 Kerberos。

Windows Challenge/Response (NTLM) 是在包括运行 Windows 操作系统的系统和独立系统上的网络上使用的身份验证协议。

Authenticate 只是一种内部方法,不知道您为什么对它和协议感到困惑,可以在这里查看内部结构:https ://blogs.msdn.microsoft.com/dsnotes/2015/12/30/negotiate -vs-ntlm/

看待这个的方法是:

  1. 微软最初想出了一种在他们称为NTLM的 Windows 服务器/机器上进行身份验证的方法,这使用了请求/响应(有时称为质询)方法。
  2. 随后他们提出了一个名为 Kerberos 的新协议,并被采用。
  3. 为了确保现有应用程序在新旧应用程序中都能正常运行,我们有一种新的身份验证方法,称为 Negotiate,它尝试了 Kerberos,如果不可用,则使用 NTLM。

编辑 1:将这些身份验证机制应用于 Web 已在RFC 4559中正式确定。

编辑 2: NTLM 对一个连接进行身份验证,而不是对请求进行身份验证,而其他身份验证机制通常对一个请求进行身份验证。在第一个用例中,这不应该有太大变化,但对于第二个用例,尝试 NTLM 并保持一个连接(通过使用 HTTP Keep-Alive,并在第一个请求中仅发送一次凭据)是有意义的。可能存在性能差异。让我们随时了解您的结果。

取自Microsoft 文档的示例 WebRequest 代码,您可以将 Webrequest 替换为 HttpWebRequest。

            // Create a request for the URL.   
            WebRequest request = WebRequest.Create(  
              "http://www.contoso.com/default.html");  
            // If required by the server, set the credentials.  
            request.Credentials = CredentialCache.DefaultCredentials;  
            // Get the response.  
            WebResponse response = request.GetResponse();  
            // Display the status.  
            Console.WriteLine (((HttpWebResponse)response).StatusDescription);  
            // Get the stream containing content returned by the server.  
            Stream dataStream = response.GetResponseStream();  
            // Open the stream using a StreamReader for easy access.  
            StreamReader reader = new StreamReader(dataStream);  
            // Read the content.  
            string responseFromServer = reader.ReadToEnd();  
            // Display the content.  
            Console.WriteLine(responseFromServer);  
            // Clean up the streams and the response.  
            reader.Close();  
            response.Close();  

推荐阅读