ROR应用如何获取Active Directory登录用户名并校验用户登录状态
解决方案
一、获取ROR应用当前登录的AD用户
你之前尝试的Etc.getlogin、system("WhoAmI")、ENV相关变量读取的都是ROR服务端进程的运行用户,和访问应用的客户端AD登录用户完全无关,无法通过这些方法获取目标用户。
根据你的应用认证方案选择对应实现:
- 如果你用Windows集成认证(IWA/ Kerberos/ NTLM):
部署时在反向代理或Web服务器中开启集成认证,认证通过后会自动把AD用户名写入REMOTE_USER请求头,ROR中直接读取即可:# 在控制器中获取 current_ad_username = request.env["REMOTE_USER"]&.split('\\')&.last # 去掉域名前缀,拿到sAMAccountName - 如果你是自主实现AD表单登录:
先通过Net::LDAP做账号密码Bind验证,验证通过后将AD用户名存入ROR Session,后续请求直接从Session读取:# 登录验证逻辑示例 ldap = Net::LDAP.new host: '你的AD域控地址', port: 389, base: 'DC=example,DC=local' username = params[:username] password = params[:password] # 拼接AD可识别的bind DN,也可以用userPrincipalName格式(username@example.local) bind_dn = "CN=#{username},CN=Users,DC=example,DC=local" if ldap.bind(method: :simple, username: bind_dn, password: password) # 验证通过,存入session session[:current_ad_user] = username # 后续请求直接取session[:current_ad_user]即可 else # 验证失败,返回登录页 end
二、判断AD用户的登录状态
你查到的lastlogon和lastlogoff默认是域控制器本地属性,不会在多域控之间同步,且仅记录用户直接登录域控的日志,普通域用户登录终端的记录默认不会更新这两个字段,所以大部分场景下返回值为0。
根据你的需求选择对应方案:
- 仅判断用户在你的ROR应用内是否登录:直接判断session中是否存在合法的AD用户名即可,这是最准确的应用内登录状态判断逻辑,不需要请求AD。
- 需要判断用户最近是否活跃在域内:查询AD的
lastLogonTimestamp属性,该属性会在多域控之间同步,默认更新周期为9-14天,可以用来判断用户近两周内是否有域登录行为:# 查询时指定返回lastLogonTimestamp属性 filter = Net::LDAP::Filter.eq("sAMAccountName", session[:current_ad_user]) ldap.search(filter: filter, attributes: ['lastLogonTimestamp', 'samaccountname', 'mail']) do |entry| # 转换Windows文件时间为Ruby时间 last_logon_ts = entry.lastLogonTimestamp.first.to_i last_logon_time = Time.at((last_logon_ts / 10000000) - 11644473600) # 示例:判断7天内有登录则认为是活跃用户 is_active = (Time.now - last_logon_time) < 7 * 24 * 3600 end - 需要判断用户当前实时登录在域终端:需要额外调用WMI接口查询对应终端的在线会话,该方案需要ROR服务账号拥有所有域终端的查询权限,且要求网络互通,一般场景下不推荐使用。
内容的提问来源于stack exchange,提问作者Avi
相关产品推荐
相关产品推荐

