express-ntlm在Firefox、Edge中未校验账号密码问题咨询
首先你对NTLM认证流程的认知存在本质偏差:没有任何浏览器会在本地校验用户输入的NTLM凭证有效性,你观察到的Chrome“自动校验账号密码”是假象。
Chrome的表现本质是两种情况:
- 你的站点在Chrome的默认可信站点列表内,域环境下Chrome直接自动透传当前Windows登录的域账号凭证发起请求,根本没有弹出账号密码输入框,你误以为是浏览器提前做了校验。
- 当你输错凭证时,服务端正确返回401状态码,Chrome触发默认重试逻辑重新弹出输入框,你误以为是浏览器本地拦截了错误密码。
Firefox、Edge的表现才是无服务端校验场景下的默认行为:如果站点不在浏览器的NTLM自动认证白名单里,浏览器会弹出输入框,收集用户输入的内容封装成NTLM认证请求头发给服务端,本地不会做任何正确性校验——毕竟浏览器本地没有存储域账号的校验数据,根本不具备判断账号密码对错的能力。
1. 能否强制Firefox、Edge在本地校验用户凭证?
不能。
浏览器作为HTTP请求的发起方,只负责按照NTLM协议规范封装用户输入的身份信息,凭证有效性校验从来都不是浏览器的职责,也没有任何配置项可以开启所谓的“本地校验”。你想要的“输错密码就被浏览器拦截、不会发到服务端”的效果,本质是服务端校验不通过返回401后,浏览器触发的重试交互,不是浏览器本地实现的校验。
2. 是否需要在服务端对接LDAP/AD完成身份校验?
必须做,这是NTLM SSO的强制要求。
你当前的实现存在严重的权限绕过漏洞:express-ntlm默认只解析NTLM请求头里的用户名,不做凭证有效性校验就放行,相当于不管用户输什么账号密码,只要格式符合NTLM协议要求就能登录系统。之前Chrome下的“正常运行”完全是交互假象,本质是服务端完全没做鉴权,和浏览器行为无关。
3. express-ntlm拿不到用户密码怎么做校验?
你不需要获取用户明文密码,express-ntlm本身已经内置了和AD/LDAP域控对接完成NTLM凭证校验的能力,不需要自己实现LDAP绑定逻辑。
只需要在初始化express-ntlm时传入域控相关配置即可,参考代码:
const express = require('express'); const ntlm = require('express-ntlm'); const app = express(); app.use(ntlm({ // 替换为你的企业域名 domain: 'COMPANYDOMAIN', // 替换为你的域控/LDAP地址 domaincontroller: 'ldap://192.168.1.10', // 校验不通过时模块会自动返回401,触发浏览器重新弹出认证框 })); app.get('/', (req, res) => { // 到这里的请求都是已经通过域控校验的合法用户 res.send(`当前登录用户:${req.ntlm.UserName}`); }); app.listen(3000);
开启上述配置后,不管用户用Chrome、Edge还是Firefox访问,只要输入的账号密码错误,模块会自动和域控完成校验并返回401,所有浏览器都会重新弹出认证框要求重新输入,和你之前在Chrome下看到的交互完全一致。
如果要让域内用户访问时不需要手动输入账号密码,直接通过当前系统登录的域账号完成认证,只需要把你的服务站点加入各浏览器的NTLM可信白名单即可:
- Chrome、Edge默认读取Windows系统「Internet选项」-「安全」-「本地Intranet」-「站点」里的配置,把你的服务域名加进去即可自动透传系统凭证。
- Firefox需要打开
about:config配置页,找到network.automatic-ntlm-auth.trusted-uris项,把你的服务域名添加到值列表里。
内容的提问来源于stack exchange,提问作者Didier68

