用issnode+IIS来托管NodeJs Server之三:加入Windows集成验证功能

这几篇文章是一个系列的:

  1.  用issnode+IIS来托管NodeJs Server之一:安装篇
  2.  用issnode+IIS来托管NodeJs Server之二:移植
  3.  用issnode+IIS来托管NodeJs Server之三:加入Windows集成验证功能
  4.  用issnode+IIS来托管NodeJs Server之四:支持Debug


今天花了一天时间,解决了NTLM身份认证的问题,现在把整个过程写下来:

1. 首先要启用网站的Windows认证,方法是:在IIS里面,选择你的站点iisCER,然后点击Authetication进行配置,你应该能看到Windows Authentication的组件,先Enable,然后再Advanced Settings里面勾选Enable Kernel-mode authentication。不然的话,无法正常认证,这个也不知道是为什么。接着,再禁用Anonymous authentication。假如你没有看到Windows Authentication组件,就需要重启下电脑。




这样一来,再访问nodeJs站点就会提示认证了(我测试下来,如果你在域里面,IE可以自动完成认证,而不必输入用户名密码,Firefox和Chrome貌似也行)。

对于配置IIS,可以参考这篇博文,作者写的很好,对我配置IIS和后面的LDAP代码帮助蛮大的:http://www.cnblogs.com/fish-li/archive/2012/05/07/2486840.html


2. IIS默认不会把身份认证的信息传给Nodejs的,所以需要手动配置一下,具体参见:https://github.com/tjanczuk/iisnode/issues/87。其实最终修改的是web.config文件(你直接添加就行了):

<iisnode promoteServerVars="AUTH_USER,AUTH_TYPE" />

3. 经过以上2步,nodeJs端就可以获得用户名了:
exports.sendReport = function (req, res) {
    var productId = req.query.productId;
    var productName = req.query.productName;
    var title = 'Send CER report';
    var page = 'page_send_report';
    var page_params = {
        title: title, header: productName,
        productId: productId, productName: productName,
        domain_account: req.headers["x-iisnode-auth_user"]
    };
用户的每一个Web请求,都会带有一个x-iisnode-auth_user头信息,里面就是用户的域账号,例如ads\fengx。用"\"分隔一下就能拿到域和用户名了。

5. 对于我来说,仅仅拿到用户名是不够的,我需要知道用户的Email地址,这个可以通过ADSI 和 LDAP协议拿到。相关代码:
using System;
using System.Diagnostics;
using System.DirectoryServices;

namespace GetAdEmailAddress
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(getEmailAddress(@"ads\someone"));
        }

        static string getEmailAddress(string domainAccount)
        {
            String[] domain_username = domainAccount.Split('\\');
            Debug.Assert(domain_username.Length == 2);

            String domain = domain_username[0];
            String user = domain_username[1];

            DirectorySearcher search = null;

            if (true)
            {
                search = new DirectorySearcher("(&(objectClass=user)(anr=" + user + "))");
            }
            else
            {
                // If we are not in a domain, we need authenticate outselves before access LDAP
                //
                DirectoryEntry entry = new DirectoryEntry(@"LDAP://ads.autodesk.com", "fengx", "test1234", AuthenticationTypes.Secure);
                search = new DirectorySearcher(entry, "(&(objectClass=user)(anr=" + user + "))");
            }

            search.PropertiesToLoad.Add("mail");
            SearchResult result = search.FindOne();
            return (result.Properties["mail"][0].ToString());

        }
    }
}
上面的代码需要引用System.DirectoryServices.dll。上面代码里面,我假如了一个if (true),假如运行这个程序的机器是在域里面的,那么直接查询就可以了,否则的话,就需要用用户名密码验证下。但是这样就有一个问题,我们的Server不在域里面!而且把用户名密码暴露在C#程序里面很危险!咋办!

5. 我们整理一下思路,首先我们的代码是iisnode模块执行的,所以我们的代码和iisnode模块在同一个进程空间(或者是父子进程的关系),而iisnode是IIS的一个模块,当然和IIS在一个进程空间。那么假如IIS已经对用户进行了身份验证(即拥有了用户的credentials),那么假如由nodeJs spawn执行上面那个获取email信息的小程序,行不行呢?哈哈,竟然可以! 相关代码如下:
app.get("/test", function (req, res) {

    var exec = require('child_process').exec;
    var getEmailAddress = exec('GetAdEmailAddress.exe', 
        {
            cwd: "./app",
            env: process.env,
        },
        function (error, stdout, stderr) {
            if (error)
                res.send(400, "failed to launch");
            else
                res.send(200,stdout);
        });
});

我没有是用spawn,而是用exec来创建进程, 原因只是exec获取stdout很方便,spawn很麻烦,但是对于stdout比较多的话,一定要用spawn,否则exec的stdout缓冲区会溢出。

6. 到此为止,大功告成!贴一下,最终的Web.Config文件(那个impersonate最好是true,但是其实false也没问题):

<configuration>
    <system.webServer>

        <handlers>
            <add name="iisnode" path="app.js" verb="*" modules="iisnode" />
        </handlers>

        <rewrite>
            <rules>
                <rule name="mysite">
                    <match url="/*" />
                    <action type="Rewrite" url="app.js" />
                </rule>
            </rules>
        </rewrite>

        <defaultDocument>
            <files>
                <add value="app.js" />
            </files>
        </defaultDocument>

        <iisnode promoteServerVars="AUTH_USER,AUTH_TYPE" />
    </system.webServer>
    <system.web>
        <identity impersonate="false" />
    </system.web>
</configuration>

7. 我开发过程中,还碰到一个严重的问题就是,我代码改了,IIS重启了,但是返回的竟然是我没有改代码前的页面,没办法,只有杀node.exe进程,让iisnode重启node.exe,这个具体是什么原因不知道,应该是iisnode的一个bug。

这篇文章是介绍IIS各种认证的,还没来得及看,先收藏下:http://www.cnblogs.com/chnking/archive/2007/11/20/965553.html


-------------------------------------------------

1. 假如开启windows认证有问题的话,可以看看这3篇博文:

http://support.microsoft.com/kb/215383/zh-cn

http://statsoft.blog.163.com/blog/static/276531322010414593971

http://blogs.iis.net/nitashav/archive/2010/03/12/iis6-0-ui-vs-iis7-x-ui-series-integrated-windows-authentication.aspx

相关代码执行:
C:\Windows\System32\inetsrv>appcmd list config /section:windowsAuthentication  
C:\Windows\System32\inetsrv>appcmd set config /section:windowsAuthentication /enabled:true  

-------------------------------------------------

附博文:http://www.cnblogs.com/fish-li/archive/2012/04/15/2450571.html,免得被博主删了。。。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值