今天安装了下wordpress,主要用于团队内部技术交流和分享。它的安装倒是非常简单,修改下数据库配置文件就可以了。但由于团队的账号全部采用LDAP进行管理,因此希望wordpress能与ldap进行集成。 好在wordpress比较成熟,有多种LDAP插件可以使用,在尝试了Simple LDAP Login和Active Directory Integration均告知失败的情况下,只好潜心去看下它的代码,代码倒简单,加上之前写过一个简单的PHP修改LDAP密码的页面,很快就定位问题并圆满解决了。 1、现将问题的修改过程和大家分享,先说下我们LDAP的组织情况,我们在LDAP创建了2个组,一个用户组,一个角色分组,用户分组按照组织架构进行区分,如下图所示: Java代码 +dc=foo,dc=bar,dc=com -+ou=roles -+ou=users --+ou=dev ---+ou=dev09 ----+uid=zhangsan 因此我们base_dn为 dc=foo,dc=bar,dc=com 2、Simple LDAP Login插件修改: a).下载并启用Simple LDAP Login b).在设置项中找到Simple LDAP Login的配置页面,填写Simple选项卡中配置baseDN、LDAP的服务器IP地址,并在Advance配置LDAP Login Attribute为uid。 c).保存后,发现输入正确的用户名和密码后,无法登陆。 d).翻了翻插件的源码才发现在Simple-LDAP-Login.php中ldap_auth方法存在问题。他将我们配置的uid、输入的用户名和配置baseDN链接在一起,即得到的是“uid=zhangsan,dc=foo,dc=bar,dc=com”作为用户的dn查找,而该正确的查找应该为“uid=zhangsan,ou=dev1,ou=dev1,ou=dev,ou=users,dc=foo,dc=bar,dc=com”,因此总是提示我们无法登陆。 Php代码 function ldap_auth( $username, $password, $directory ) { $result = false; if ( $directory == "ad" ) { $result = $this->adldap->authenticate( $username, $password ); } elseif ( $directory == "ol" ) { $this->ldap = ldap_connect( join(' ', (array)$this->get_setting('domain_controllers')), (int)$this->get_setting('ldap_port') ); ldap_set_option($this->ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$this->get_setting('ldap_version')); if ( str_true($this->get_setting('use_tls')) ) { ldap_start_tls($this->ldap); } $ldapbind = @ldap_bind($this->ldap, $this->get_setting('ol_login') .'=' . $username . ',' . $this->get_setting('base_dn'), $password); $result = $ldapbind; } return apply_filters($this->prefix . 'ldap_auth', $result); } e).修改查找部分,先用uid去查找正确的dn,然后用正确的dn和password去绑定,红色部分为修改。 f).最终代码如下: Php代码 function ldap_auth( $username, $password, $directory ) { $result = false; if ( $directory == "ad" ) { $result = $this->adldap->authenticate( $username, $password ); } elseif ( $directory == "ol" ) { $this->ldap = ldap_connect( join(' ', (array)$this->get_setting('domain_controllers')), (int)$this->get_setting('ldap_port') ); ldap_set_option($this->ldap, LDAP_OPT_PROTOCOL_VERSION, (int)$this->get_setting('ldap_version')); if ( str_true($this->get_setting('use_tls')) ) { ldap_start_tls($this->ldap); } //add by gogo1217 $search=@ldap_search($this->ldap,$this->get_setting('base_dn'),$this->get_setting('ol_login') .'=' .$username); $dn=@ldap_get_entries($this->ldap,$search); //从获取到的数组取出用户dn,没有用户dn修改不了密码。 for ($i=0; $i<$dn["count"]; $i++){ $user_dn= $dn[$i]["dn"]; } $ldapbind = @ldap_bind($this->ldap, $user_dn, $password); //end by gogo1217 //$ldapbind = @ldap_bind($this->ldap, $this->get_setting('ol_login') .'=' . $username . ',' . $this->get_setting('base_dn'), $password); $result = $ldapbind; } return apply_filters($this->prefix . 'ldap_auth', $result); } g).LDAP中姓名中文乱码问题: 这是因为插件中对中文进行了转码,去掉转码即可,删除红颜色部分中的sanitize_title函数包裹: 3、Active Directory Integration插件修改: a).下载并启用Active Directory Integration; b).在配置模块中找到Active Directory Integration Settings,填写Server选项卡中的LDAP的服务器IP地址和baseDN。 c).保存后,发现输入正确的用户名和密码后,无法登陆。 d).翻了翻插件的源码,发现使用ad_ldap/adLDAP.php来链接LDAP,他将输入的用户名和我们在User配置页面中用户后缀链接在一起,由于我没有配置后缀即得到的是“zhangsan”作为用户的dn查找,而该正确的查找应该为“uid=zhangsan,ou=dev1,ou=dev1,ou=dev,ou=users,dc=foo,dc=bar,dc=com”,因此总是提示我们无法登陆。 Php代码 /** * Validate a user's login credentials * * @param string $username A user's AD username * @param string $password A user's AD password * @param bool optional $prevent_rebind * @return bool */ public function authenticate($username, $password, $prevent_rebind = false) { // Prevent null binding if ($username === NULL $password === NULL) { return false; } if (emptyempty($username) emptyempty($password)) { return false; } // Bind as the user $ret = true; $this->_bind = @ldap_bind($this->_conn, $username . $this->_account_suffix, $password); if (!$this->_bind){ $ret = false; } e).修改查找部分,先用uid去查找正确的dn,然后用正确的dn和password去绑定,红色部分为修改。 f).最终代码如下: Php代码 /** * Validate a user's login credentials * * @param string $username A user's AD username * @param string $password A user's AD password * @param bool optional $prevent_rebind * @return bool */ public function authenticate($username, $password, $prevent_rebind = false) { // Prevent null binding if ($username === NULL $password === NULL) { return false; } if (emptyempty($username) emptyempty($password)) { return false; } // Bind as the user $ret = true; //add by liushimin $search=@ldap_search($this->_conn,$this->_base_dn,"uid=".$username); $dn=@ldap_get_entries($this->_conn,$search); //从获取到的数组取出用户dn,没有用户dn修改不了密码。 for ($i=0; $i<$dn["count"]; $i++){ $user_dn= $dn[$i]["dn"]; } //end by liushimin $this->_bind = @ldap_bind($this->_conn, $user_dn, $password); //$this->_bind = @ldap_bind($this->_conn, $username . $this->_account_suffix, $password); if (!$this->_bind){ $ret = false; } 4、对比2个插件,都是在用户登陆的时候去LDAP检索,并且发现本地没有用户,则创建一个新的用户并赋予指定的角色。