使用脚本进行身份验证

本部分演示如何编写使用 WinHttpRequest 对象从需要 HTTP 身份验证的服务器访问数据的脚本。

先决条件和要求

除了 Microsoft JScript 的实践知识外,此示例还要求满足以下条件:

  • Microsoft Windows 软件开发工具包的当前版本 (SDK) 。
  • 如果通过代理服务器连接到 Internet,则为 Microsoft Windows HTTP Services (WinHTTP) 建立代理设置的代理配置工具。 有关详细信息 ,请参阅Proxycfg.exe代理配置工具
  • 熟悉 网络术语 和概念。

使用身份验证访问网站

若要创建演示身份验证的脚本,请执行以下操作:

  1. 打开文本编辑器,例如 Microsoft 记事本。

  2. 将“[authenticationSite]”替换为相应的文本后,将以下代码复制到文本编辑器中,以指定需要 HTTP 身份验证的站点的 URL。

    // Load the WinHttpRequest object.
    var WinHttpReq = 
              new ActiveXObject("WinHttp.WinHttpRequest.5.1");
    
    function getText1( )
    {
      // Specify the target resource.
      WinHttpReq.open( "GET", 
                       "https://[authenticationSite]", 
                       false;
    
      // Send a request to the server and wait for a response.
      WinHttpReq.send( );
    
      // Display the results of the request.
      WScript.Echo( "No Credentials: " );
      WScript.Echo( WinHttpReq.Status + "   " + WinHttpReq.StatusText);
      WScript.Echo( WinHttpReq.GetAllResponseHeaders);
      WScript.Echo( );
    };
    
    function getText2( )
    {
      // HttpRequest SetCredentials flags
      HTTPREQUEST_SETCREDENTIALS_FOR_SERVER = 0;
    
      // Specify the target resource.
      WinHttpReq.open( "GET", 
                       "https://[authenticationSite]", 
                       false );
    
      // Set credentials for server.
      WinHttpReq.SetCredentials( "User Name", 
                                 "Password",
                                 HTTPREQUEST_SETCREDENTIALS_FOR_SERVER);
    
      // It might also be necessary to supply credentials 
      // to the proxy if you connect to the Internet 
      // through a proxy that requires authentication.
    
      // Send a request to the server and wait for 
      // a response.
      WinHttpReq.send( );
    
      // Display the results of the request.
      WScript.Echo( "Credentials: " );
      WScript.Echo( WinHttpReq.Status + "   " + WinHttpReq.StatusText );
      WScript.Echo( WinHttpReq.GetAllResponseHeaders( ) );
      WScript.Echo( );
    };
    
    getText1( );
    getText2( );
    
  3. 将文件另存为“Auth.js”。

  4. 在命令提示符下,键入“cscript Auth.js”,然后按 Enter。

现在,你有一个以两种不同的方式请求资源的程序。 第一种方法在不提供凭据的情况下请求资源。 返回 401 状态代码以指示服务器需要身份验证。 响应标头也会显示,应如下所示:

Connection: Keep-Alive
Content-Length: 0
Date: Fri, 27 Apr 2001 01:47:18 GMT
Content-Type: text/html
Server: Microsoft-IIS/5.0
WWW-Authenticate: NTLM
WWW-Authenticate: Negotiate
Cache-control: private

尽管响应指示对资源的访问被拒绝,但它仍然返回几个标头,这些标头提供有关资源的一些信息。 名为“WWW-Authenticate”的标头指示服务器需要对此资源进行身份验证。 如果存在名为“Proxy-Authenticate”的标头,则表示代理服务器需要身份验证。 每个身份验证标头都包含可用的身份验证方案,有时还包含一个领域。 领域值区分大小写,并定义一组应接受相同凭据的服务器或代理。

有两个名为“WWW-Authenticate”的标头,指示支持多个身份验证方案。 如果调用 GetResponseHeader 方法来查找“WWW-Authenticate”标头,该方法仅返回该名称的第一个标头的内容。 在这种情况下,它将返回值“NTLM”。 若要确保处理标头的所有匹配项,请改用 GetAllResponseHeaders 方法。

第二个方法调用请求相同的资源,但首先通过调用 SetCredentials 方法提供身份验证凭据。 以下代码部分演示如何使用此方法。

WinHttpReq.SetCredentials( "User Name", "Password",
                               HTTPREQUEST_SETCREDENTIALS_FOR_SERVER);

此方法将用户名设置为“UserName”,将密码设置为“Password”,并指示授权凭据应用于资源服务器。 身份验证凭据也可以发送到代理。

提供凭据后,服务器将返回 200 状态代码,指示可以检索文档。

检查状态代码

前面的示例是说明性的,但它要求用户显式提供凭据。 在必要时提供凭据,在不需要时不提供凭据的应用程序更有用。 若要实现执行此操作的功能,必须修改示例,以检查随响应一起返回的状态代码。

有关可能的状态代码的完整列表以及说明,请参阅 HTTP 状态代码。 但是,对于此示例,应只遇到三个代码中的一个。 状态代码为 200 表示资源可用且正在随响应一起发送。 状态代码 401 指示服务器需要身份验证。 状态代码 407 指示代理需要身份验证。

通过将“getText2”函数替换为以下代码来修改在上一部分中创建的示例, (将“[authenticationSite]”替换为你自己的文本,以指定需要 HTTP 身份验证) 站点的 URL:

function getText2() {
  WScript.Echo( "Credentials: " );

  // HttpRequest SetCredentials flags.
  HTTPREQUEST_SETCREDENTIALS_FOR_SERVER = 0;
  HTTPREQUEST_SETCREDENTIALS_FOR_PROXY = 1;

  // Specify the target resource.
  var targURL = "https://[authenticationSite]";
  WinHttpReq.open( "GET", targURL, false );

  var Done = false;
  var Attempts = 0;
  do
  {
    // Keep track of the number of request attempts.
    Attempts++;

    // Send a request to the server and wait for a response.
    WinHttpReq.send( );

    // Obtain the status code from the response.
    var Status = WinHttpReq.Status;

    switch (Status)
    {
      // A 200 status indicates that the resource was retrieved.
      case 200:
        Done = true;
        break;

      // A 401 status indicates that the server 
      // requires authentication.
      case 401:
        WScript.Echo( "Requires Server UserName and Password." );

        // Specify the target resource.
        WinHttpReq.open( "GET", targURL, false );

        // Set credentials for the server.
        WinHttpReq.SetCredentials( "User Name", 
                             "Password",
                              HTTPREQUEST_SETCREDENTIALS_FOR_SERVER);
        break;

      // A 407 status indicates that the proxy 
      // requires authentication.
      case 407:
        WScript.Echo( "Requires Proxy UserName and Password." );

        // Specify the target resource.
        WinHttpReq.open( "GET", targURL, false );

        // Set credentials for the proxy.
        WinHttpReq.SetCredentials( "User Name", 
                              "Password",
                              HTTPREQUEST_SETCREDENTIALS_FOR_PROXY );
        break;
    }
  } while( ( !Done ) && ( Attempts < 3 ) );

  // Display the results of the request.
  WScript.Echo( WinHttpReq.Status + "   " + WinHttpReq.StatusText );
  WScript.Echo( WinHttpReq.GetAllResponseHeaders( ) );
  WScript.Echo( );
};

同样,保存并运行文件。 第二种方法仍检索文档,但它仅在需要时提供凭据。 “getText2”函数执行 OpenSend 方法,就像不需要身份验证一样。 使用 Status 属性检索状态,switch 语句响应生成的状态代码。 如果状态为 401 (服务器需要身份验证) 或 407 (代理要求身份验证) ,则再次执行 Open 方法。 然后是 SetCredentials 方法,该方法设置用户名和密码。 然后,代码循环回到 Send 方法。 如果在三次尝试后无法成功检索资源,则该函数将停止执行。

WinHTTP 中的身份验证

WinHttpRequest

SetCredentials

HTTP/1.1 征求意见 (RFC 2616)