node.js 客户端中的 Windows 集成身份验证

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13949163/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 16:47:34  来源:igfitidea点击:

Windows Integrated Authentication in node.js Client

node.jswindowswindows-authenticationnode.js-client

提问by laktak

When using node.js as a client, is it possible to connect to a server using Windows integrated authentication (e.g. when connecting to IIS)?

当使用 node.js 作为客户端时,是否可以使用 Windows 集成身份验证连接到服务器(例如连接到 IIS 时)?

My searches for this only turn up results where node.js is used as a server.

我对此的搜索只会显示将 node.js 用作服务器的结果。

回答by josh3736

2015 Update:There are now some modules that implement Windows-integrated authentication. node-sspiuses SSPI (the Windows security API) to handle the server side of things, but does not do client auth. There are several client implementationssuch as http-ntlm, but they are not truly integrated since they require the user password -- they do not use SSPI to do transparent auth.

2015 更新:现在有一些模块可以实现 Windows 集成的身份验证。 node-sspi使用 SSPI(Windows 安全 API)来处理服务器端的事情,但不执行客户端身份验证。有几个客户端实现,例如http-ntlm,但它们并没有真正集成,因为它们需要用户密码——它们不使用 SSPI 进行透明身份验证。

2019 Update:It appears to be possible to use the kerberoslibrary to do true Windows-integrated HTTP auth using SSPI (ie, use the node process' token to do transparent auth). See kerberos-agent. Obviously this uses Kerberos rather than NTLM/Negotiate, so this may or may not work depending on your exact situation.

2019 年更新:似乎可以使用kerberos库使用 SSPI 进行真正的 Windows 集成 HTTP 身份验证(即,使用节点进程的令牌进行透明身份验证)。请参阅kerberos-agent。显然,这使用 Kerberos 而不是 NTLM/Negotiate,因此这可能会或可能不会起作用,具体取决于您的具体情况。



"Windows integrated authentication" is what's known as NTLM authentication. When you receive a HTTP 401 from IIS with a WWW-Authenticateheader containing NTLM, you now have the fun of implementing the NTLM authentication protocol. Quoting from this document about the NTLM authentication protocol:

“Windows 集成身份验证”就是所谓的 NTLM 身份验证。当您从 IIS 收到带有WWW-Authenticate包含的标头的 HTTP 401 时NTLM,您现在可以享受实现 NTLM 身份验证协议的乐趣。引用本文档中有关 NTLM 身份验证协议的内容



  1. The client requests a protected resource from the server:

    GET /index.html HTTP/1.1
    
  2. The server responds with a 401status, indicating that the client must authenticate. NTLMis presented as a supported authentication mechanism via the WWW-Authenticateheader. Typically, the server closes the connection at this time:

    HTTP/1.1 401 Unauthorized
    WWW-Authenticate: NTLM
    Connection: close
    

    Note that Internet Explorer will only select NTLM if it is the first mechanism offered; this is at odds with RFC 2616, which states that the client must select the strongest supported authentication scheme.

  3. The client resubmits the request with an Authorizationheader containing a Type 1 messageparameter. The Type 1 message is Base-64 encoded for transmission. From this point forward, the connection is kept open; closing the connection requires reauthentication of subsequent requests. This implies that the server and client must support persistent connections, via either the HTTP 1.0-style "Keep-Alive" header or HTTP 1.1 (in which persistent connections are employed by default). The relevant request headers appear as follows:

    GET /index.html HTTP/1.1
    Authorization: NTLM TlRMTVNTUAABAAAABzIAAAYABgArAAAACwALACAAAABXT1JLU1RBVElPTkRPTUFJTg==
    
  4. The server replies with a 401status containing a Type 2 messagein the WWW-Authenticateheader (again, Base-64 encoded). This is shown below.

    HTTP/1.1 401 Unauthorized
    WWW-Authenticate: NTLM TlRMTVNTUAACAAAADAAMADAAAAABAoEAASNFZ4mrze8AAAAAAAAAAGIAYgA8AAAARABPAE0AQQBJAE4AAgAMAEQATwBNAEEASQBOAAEADABTAEUAUgBWAEUAUgAEABQAZABvAG0AYQBpAG4ALgBjAG8AbQADACIAcwBlAHIAdgBlAHIALgBkAG8AbQBhAGkAbgAuAGMAbwBtAAAAAAA=
    
  5. The client responds to the Type 2 message by resubmitting the request with an Authorizationheader containing a Base-64 encoded Type 3 message:

    GET /index.html HTTP/1.1
    Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGoAAAAYABgAggAAAAwADABAAAAACAAIAEwAAAAWABYAVAAAAAAAAACaAAAAAQIAAEQATwBNAEEASQBOAHUAcwBlAHIAVwBPAFIASwBTAFQAQQBUAEkATwBOAMM3zVy9RPyXgqZnr21CfG3mfCDC0+d8ViWpjBwx6BhHRmspst9GgPOZWPuMITqcxg==
    
  6. Finally, the server validates the responses in the client's Type 3 message and allows access to the resource.

     HTTP/1.1 200 OK
    
  1. 客户端从服务器请求受保护的资源:

    GET /index.html HTTP/1.1
    
  2. 服务器以401状态响应,指示客户端必须进行身份验证。NTLM通过WWW-Authenticate标头显示为受支持的身份验证机制。通常,服务器此时关闭连接:

    HTTP/1.1 401 Unauthorized
    WWW-Authenticate: NTLM
    Connection: close
    

    请注意,如果它是第一个提供的机制,Internet Explorer 只会选择 NTLM;这与 RFC 2616 不一致,RFC 2616 规定客户端必须选择支持的最强身份验证方案。

  3. 客户端使用Authorization包含类型 1 消息参数的标头重新提交请求。类型 1 消息采用 Base-64 编码进行传输。从现在开始,连接保持打开状态;关闭连接需要对后续请求重新进行身份验证。这意味着服务器和客户端必须通过 HTTP 1.0 样式的“Keep-Alive”标头或 HTTP 1.1(默认使用持久连接)来支持持久连接。相关的请求头如下所示:

    GET /index.html HTTP/1.1
    Authorization: NTLM TlRMTVNTUAABAAAABzIAAAYABgArAAAACwALACAAAABXT1JLU1RBVElPTkRPTUFJTg==
    
  4. 与该服务器的应答401包含状态类型2消息WWW-Authenticate标题(再次,BASE-64编码)。这如下所示。

    HTTP/1.1 401 Unauthorized
    WWW-Authenticate: NTLM TlRMTVNTUAACAAAADAAMADAAAAABAoEAASNFZ4mrze8AAAAAAAAAAGIAYgA8AAAARABPAE0AQQBJAE4AAgAMAEQATwBNAEEASQBOAAEADABTAEUAUgBWAEUAUgAEABQAZABvAG0AYQBpAG4ALgBjAG8AbQADACIAcwBlAHIAdgBlAHIALgBkAG8AbQBhAGkAbgAuAGMAbwBtAAAAAAA=
    
  5. 客户端通过使用Authorization包含 Base-64 编码的类型 3 消息的标头重新提交请求来响应类型 2消息

    GET /index.html HTTP/1.1
    Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGoAAAAYABgAggAAAAwADABAAAAACAAIAEwAAAAWABYAVAAAAAAAAACaAAAAAQIAAEQATwBNAEEASQBOAHUAcwBlAHIAVwBPAFIASwBTAFQAQQBUAEkATwBOAMM3zVy9RPyXgqZnr21CfG3mfCDC0+d8ViWpjBwx6BhHRmspst9GgPOZWPuMITqcxg==
    
  6. 最后,服务器验证客户端类型 3 消息中的响应并允许访问资源。

     HTTP/1.1 200 OK
    


You'll have to figure out how you'll reply to the Type 2 message's challenge, where the user's password is MD4 hashed and used to create DES keys to encrypt the challenge data.

您必须弄清楚您将如何回复类型 2 消息的挑战,其中用户的密码是 MD4 散列并用于创建 DES 密钥以加密挑战数据。

I'm not sure how you'd get access to the logged in user's credential data which would allow you to accomplish this, though I'm sure it would involve writing a native C++ addonso you could talk to the necessary Windows API. Or, I suppose you could just ask for the user's password.

我不确定您将如何访问登录用户的凭据数据,这将允许您完成此操作,但我确定这将涉及编写本机 C++ 插件,以便您可以与必要的 Windows API 对话。或者,我想您可以只询问用户的密码。

Alternatively, you could proxy your Node requests through software that handles the NTLM mess for you.

或者,您可以通过为您处理 NTLM 混乱的软件代理您的 Node 请求

回答by DaNeSh

For Kerberos:

对于 Kerberos:

  • node-sspi

    Just on windows
    No client side node
    Supports NTLM too
    
  • passport-negotiate

    Needs python on the server
    it's a passportJs strategy
    
  • 节点 sspi

    Just on windows
    No client side node
    Supports NTLM too
    
  • 护照谈判

    Needs python on the server
    it's a passportJs strategy
    

For NTLM

对于 NTLM

  • node-sspi

    Just on windows
    No client side node
    Supports Kerberos too
    
  • httpntlm
  • express-ntlm
  • request-ntlm
  • ntlm

    experimental project!
    
  • ntlm-auth

    experimental!
    
  • passport-ntlm

    supports SMB protocol
    it's a passportJs strategy
    
  • 节点 sspi

    Just on windows
    No client side node
    Supports Kerberos too
    
  • httpntlm
  • express-ntlm
  • 请求-ntlm
  • 网络

    experimental project!
    
  • ntlm-auth

    experimental!
    
  • 护照-ntlm

    supports SMB protocol
    it's a passportJs strategy
    

I chose passport-negotiate for Kerberos and express-ntlm for NTLM

我为 Kerberos 选择了passport-negotiate,为NTLM 选择了express-ntlm

回答by zumalifeguard

For client side, what works is to use node-libcurl to do REST / HTTP calls.

对于客户端,有效的是使用 node-libcurl 进行 REST / HTTP 调用。

here's sample code:

这是示例代码:

var endpoint = urlString;
var url = require("url");
var endpointUrl = url.parse(endpoint);

var Curl = require( 'node-libcurl' ).Curl;
var curl = new Curl();

curl.setOpt( 'USERNAME', '' );
//curl.setOpt( 'VERBOSE', 1 );
curl.setOpt( 'URL', endpoint );
curl.setOpt( 'HTTPAUTH', Curl.auth.NEGOTIATE );
curl.setOpt( 'NOPROXY', endpointUrl.hostname );

curl.on( 'end', function( statusCode, body, headers ) {

    if (statusCode === 200) {
        console.log(body);
        cb(null, { statusCode, body, headers } ); 
    } else {
        cb(new Error(), { statusCode, body, headers } ); 
    }

    this.close();
});

curl.on( 'error', curl.close.bind( curl ) );
curl.perform();