nginx代理windowsAD域认证 ntlm认证处理
使用场景
公司登陆内网项目需要使用windows域认证(以下简称AD域或AD认证),但是,不是在项目中使用LDAP去认证(nginx配置LDAP的朋友可以闪了),而是在.net中写的一个认证,给了一个get链接,返回用户名和token。
然后前端页面登陆时,会先调用这个地址,获取用户信息后再给项目认证。
问题有两点:
- 因为跨域,所以前端需要使用jsonp
- 我们项目全是使用的nginx代理,使用的http协议,当需要升级https协议时,只需要在nginx中配置。但是AD认证这里只有http,当页面使用https时,默认调用AD也会使用https。
所以这里我们需要把AD认证也配置到nginx中。这样不存在跨域和协议不同的问题。
开始配置
直接在nginx配置转发
问题来了
使用代理的链接,居然弹出了认证页面?
这个我先忍它一波,于是我输入了账号密码,点击登陆!
好家伙,还弹?难道手速太快输错了??再试一波,还弹??
哪里出了问题?难道认证用的是本机ip??
于是我修改了nginx中的转发配置。还是一样的结果。
莽(你知道莽村的莽是怎么来的么?)试了好久还是弹弹弹,难受。这就是不知道原理硬上的结果
使用postman测试
直接写入AD认证的地址,得先有个正确结果不是。
直接访问应该是不行,没有认证信息啊?
做为一个面向搜索引擎的开发,直接搜索postman怎么认证windowsAD域
结果如下:
好了,正常的结果已经出现,怎么能够停止不前。
于是我换上了nginx代理的链接。
意料之中,科学之外(这不科学啊!!!)
暂时没有思路,所以也无法面向搜索开发了
先吃个午饭,再说…
果然,时间能解决一切,我想到了一个问题,我看看postman发送的请求有啥不相同呗!
于是:
咦??怎么发了3次请求?
请看这3次的请求和返回:
第一个请求:
第二个请求
第三个请求
这应该是认证过程,注意这个NTLM和postman中的认证名字一样
于是我又打开了搜索引擎(天晴了,雨停了,我觉得我又行了),搜索NTLM认证原理。
果然,不愧是搜索引擎,很快我就知道了这个认证的原理。
大概就是3次认证需要同一个连接,但是nginx这里的3次连接都不是同一个,所以需要处理。(需要懂原理的自行搜索,我就不重复了)。
nginx配置NTLM
直接打开nginx,上配置
http {
upstream windowsAdStream {
server 服务ip:服务端口; #多个ip时可配置多个server
keepalive 1; # 必须设置,最大空闲连接,不建议设置过大值。
#配置意思是使用多少次后关闭该长连接
# 注:重点!!!必须配置,且必须是3,这个配置虽然是可选设置,但是因为认证需要的是3次,如果这里配置少于3,那么认证会失败,会有弹框!当然,如果你页面再刷新一次,相当于4次,那第3次时会认证成功。如果你大于3,相当于你认证后,keepalive_timeout 秒后才会关闭该长连接,那这个时间内,另一个用户访问时,会直接得到你的认证信息!
keepalive_requests 3;
keepalive_timeout 3s; # 可选设置,keepalive conn 超时关闭时间。看自己网络等需求设置大小,这里最好别设置太长
}
#域认证转发
location /DomainUser {
proxy_pass http://windowsAdStream;
# 必须设置下面这两个配置,否则不会生效。
proxy_http_version 1.1;
proxy_set_header Connection "";
}
}
注:再次说明重点 keepalive_requests 必须设置为3,每次认证(使用3次)后,都关掉该长连接。否则认证信息会窜台的…
执行 nginx -t 看看配置是否可用。
成功了就直接 nginx -s reload。
如果没有成功,看看配置没错的话,是否缺少模块,缺少模块自己索引一下怎么添加哪个模板。
成果
肯定是搞定了啊。O(∩_∩)O哈哈~
问题大了…
不上测试不知道,一上测试问题来了…
因为建立的是长连接,会导致2个或者多个用户同时认证时,可能会返回别人的信息,比如张三和李四同时认证,然后张三的电脑返回了李四的info,
把keepalive_requests 设置为3,keepalive_timeout 设置为1,只能减少几率,但是并发上来,还是得凉,这肯定不允许啊。
靠nginx本身的配置肯定是搞不定了(nginx plus可以解决,毕竟收费,有ntlm功能…[手动狗头]),这里我觉得应该加一个配置,同一个ip建立一个长连接,但是暂时不会c语言,没法写模块。
再次解决
于是发挥我搜索的能力,找了半天,发现nginx本身是支持ntlm的,但是 是nginx plus版本,也就是需要付费版。
那不能,没赚钱怎么能花钱。
于是我换个搜索引擎再搜搜,发现了大佬写的ntlm模块,只需要下载下来,然后解压,按说明添加模板,在upstream中加一个 ntlm;参数就行了。地址如下:
https://github.com/gabihodoroaga/nginx-ntlm-module
在linux中使用unzip解压,然后有两种添加方式
./configure \
--add-module=../nginx-ntlm-module
./configure \
--add-dynamic-module=../nginx-ntlm-module
我使用的是第一种,然后配置后,关掉nginx,重新启动。
http {
upstream windowsAdStream {
ntlm; #模块中只需要加这个配置
server 服务ip:服务端口; #多个ip时可配置多个server
}
#域认证转发
location /DomainUser {
proxy_pass http://windowsAdStream;
# 必须设置下面这两个配置,否则不会生效。
proxy_http_version 1.1;
proxy_set_header Connection "";
}
}