如何使用Ruby1.9.2和roryO的net-ldap-gem从RubyOnRails3修改ActiveDirectory中的userAccountControl?

我想要做的是启用/禁用Active Directory Useraccount。 在Active Directory中,信息作为HEX值存储在名为userAccessControl的属性中的位寄存器中。 在我们的Windows 2008 Server R1中,启用帐户的0x10200,用户密码永不过期,或者禁用帐户的0x10202,用户密码永不过期。

现在只需触摸启用/禁用信息的标志,我写了以下方法……

def set_account_active_flag(activate) success = false get_aduser if @aduser.nil? puts "#####################################" unless @uac.nil? || @uac.blank? tmpuac = @uac.to_i tmpuac = activate ? tmpuac & 2 == 0 ? tmpuac | 2 : tmpuac : tmpuac & 2 == 2 ? tmpuac ^ 2 : tmpuac ldap_con = self.class.initialize_ldap_con # success = ldap_con.replace_attribute ldap_encode(@dn), :userAccountControl, tmpuac success = ldap_con.replace_attribute ldap_encode(@dn), :userAccountControl, ldap_encode(tmpuac.to_s) else puts ">>>>>\nuserAccessControl-Register is not available\n<<<< e puts "NET::LDAP::LdapError\n#{e}" ensure puts "-------------------------------------" puts "LDAP operation failed (#{ldap_con.get_operation_result.code}):" puts "-------------------------------------" puts ldap_con.get_operation_result.message puts "#####################################" return success end 

好的…内部:

  • get_aduser只是一个加载一组广告属性的方法([‘dn’,’userPrincipalName’,’givenname’,’sn’,’mail’,’memberof’,’userAccountControl’])并将它们存储到实例中 – 尝试登录的用户的变量(@dn,@ user_principal_name,@ first_name,@ original_name,@ groups,@ uac)

那部分就像一个魅力。 @uac(作为字符串返回),我可以转换为整数

 x = @uac.to_i 

然后使用它作为位寄存器来检查和修改标志

 x & 2 # => 0 if unset, => 1 if set x |= 2 # sets the flag x ^= 2 # unsets the flag 

这工作我认为只是将该值写回我的Active Directory很容易。

我的问题出现了:到目前为止,我尝试将新的userAccountControl值写回整数字符串 ,但两次尝试都失败了,尽管两种情况下的operation-result-message都是{Code:0,Message:’Success’}

尝试将新的userAccessControl值写回整数引发NET :: LDAP :: LdapError

 ##################################### NET::LDAP::LdapError response missing or invalid ------------------------------------- LDAP operation failed (0): ------------------------------------- Success ##################################### => false 

尝试将新的userAccessControl值写回字符串不会引发错误,但仍会导致错误

 ##################################### ------------------------------------- LDAP operation failed (0): ------------------------------------- Success ##################################### => false 

所以我想知道,“我做错了什么?”

有人知道如何将userAccessControl写回ActiveDirectory吗?

我是否必须使用写回用户密码所需的笨拙算法来转换新的userAccessControl-Value?

非常感谢任何有用的提示甚至解决方案。

最好的祝福,

Ingo Gambin

好吧,从玩弄所有ldap连接的东西,并尝试了几种不同的方法,比如使用我在rails中执行的php脚本编写整个节目,似乎实际上在编写修改后的值时没有真正的问题!

我做错了什么? 什么都没有 ! ……好吧……或多或少……那是……

为什么我没有意识到上述方法“有点”有效?

  • 让ActiveDirectory SnapIn查看用户列表并没有在点击’F5’时实现微小的’停用’图标…实际上我假设F5会完全实现列表……但事实并非如此。 所以我没有看到那里的变化。
  • 上面的代码包含一点逻辑错误。 由于上述方法假设AD控制标志被称为“帐户活动”,而不是这种情况,因此标志为“帐户已停用”,而不是启用帐户禁用,反之亦然。 所以设置标志意味着DEACTIVATION,这与我上面的方法相反。
  • 除了AD-Account-DEACTIVATION-Flag之外,我们的用户记录中还有一个类似的标志。 我的测试用户实际上已在那里被禁用,并且直接调用了LDAP-Modification而没有设置用户记录设置=>所以即使未禁用AD帐户,我的测试用户记录仍然被禁用并且不允许登录。
  • 最后但并非最不重要的:替换’userAccountControl’值的实际尝试的返回值保持返回false(并且仍然在下面给出的正确解决方案中),即使修改成功:

      success = ldap_con.replace_attribute ldap_encode(@dn), :userAccountControl, ldap_encode(tmpuac.to_s) 

这里设置Account Deactivation的固定方法(以及要写回的值应该是一个字符串):

 def set_account_deactivation(deactivate) get_aduser if @dn.nil? success = false unless @uac.nil? || @uac.blank? tmpuac = @uac.to_i # deactivate = true means 'Account Deactivated'-flag => false tmpuac = deactivate ? tmpuac & 2 == 0 ? tmpuac | 2 # flag not set (active) = account is not deactivated ? deactivate : tmpuac # : leave as is : tmpuac & 2 == 2 ? tmpuac ^ 2 # flag set (deactivated) = account is deactivated ? activate : tmpuac # : leave as is ldap_con = self.class.initialize_ldap_con success = ldap_con.replace_attribute ldap_encode(@dn), :useraccountcontrol, ldap_encode("#{tmpuac}") else puts "Failed to read userAccessControl-Register!" end rescue Net::LDAP::LdapError => e puts "NET::LDAP::LdapError\n#{e}" ensure return success end def ldap_encode(string) if string.encoding.name != 'ASCII-8BIT' string.dup.force_encoding 'ASCII-8BIT' else string end end