发一个支持openldap (SSHA方式加密)的扩展
今天用了整一天的时间尝试为禅道加上LDAP认证支持,参考了不少相关的文章,终于成功搞定。有高手做的LDAP插件,不过我没用成功。主要参考了这篇文章http://jkers.blog.51cto.com/3016670/579787 以及OPENLDAP使用SSHA加密验证的相关文章,经过不停的低效率的使用ECHO调试,终于搞定了这么一个东西。改的是identify.php这个文件,已经是在今天发布的新补丁的基础上修改的,有需要用的朋友不需担心今天官方修复的问题,可以修改文件中LDAP服务器的相关配置就可以使用了。
遗憾不能上附件,那么我把代码贴下面吧:
public function identify($account, $password)
{
if(!$account or !$password) return false;
/**
*ldap验证程序块,其中目录树的uid可以取同一个值,只要返回的数组(count>=1)其中有一项密码值通过验证,则表示通过ldap验证;
*系统则不在重复验证密码,但还要验证用户名,因为要检查数据的完整性.
*----------------------------------------Start---------------------------------------------*/
$ldaphost="127.0.0.1"; //LDAP服务器地址
$ldapport=389; //LDAP监听端口
$ldapUid="cn=Manager,dc=ifreecomm,dc=com"; //绑定的LDAP DN
$ldapPwd="123456"; // 绑定DN的密码
$base_dn="dc=ifreecomm,dc=com";
$filter="uid=".$account;
$attributes=array("userPassword");
$ds=ldap_connect($ldaphost,$ldapport) or die(js::error($this->lang->user->loginFailed));
if($ds){
ldap_set_option ( $ds, LDAP_OPT_PROTOCOL_VERSION, 3 );
ldap_set_option ( $ds, LDAP_OPT_REFERRALS, 0 ); // Binding to ldap server
$bd = ldap_bind($ds, $ldapUid, $ldapPwd) or die(js::error($this->lang->user->loginFailed));
$sr=ldap_search($ds, $base_dn, $filter,$attributes);
$count=ldap_count_entries($ds, $sr);
if($count>0){
$info=ldap_get_entries($ds, $sr);
$ispass=FALSE;
for($i=0;$i<$info['count'];$i++){
/**
*这一段代码是处理以SSHA方式加密密码的OpenLdap认证,如果用AD或者使用不同加密方式,
*需要相应的修改下面这部分代码
*/
$arrpwd=$info[$i]['userpassword'][0];
$ohash = base64_decode(substr($arrpwd,6));
$osalt = substr($ohash,20);
$ohash = substr($ohash,0,20);
$nhash = pack("H*",sha1($password.$osalt));
if($ohash == $nhash){
$ispass=TRUE;
break;
}
}
if($ispass){//通过LDAP认证之后,同步zentao数据库,我不是phper,所以是凭感觉这么干的,有没有安全问题我不知道
$pre_record = $this->dao->select('*')->from(TABLE_USER)
->where('account')->eq($account)
->fetch();
if(!$pre_record){
$this->dao->insert(TABLE_USER)->set('password')->eq(md5($password))
->set('account')->eq($account)
->set('realname')->eq($account)
->set('company')->eq(1)
->exec();
}else{
$this->dao->update(TABLE_USER)->set('password')->eq(md5($password))
->where('account')->eq($account)->exec();
}
}else{
die(js::error($this->lang->user->loginFailed));die(1);
}
}else{
die(js::error($this->lang->user->loginFailed));die(2);
}
ldap_unbind($ds);
}
ldap_close($ds);
/*-------------------------------------End------------------------------------------------*/
/* Get the user first. If $password length is 32, don't add the password condition. */
$record = $this->dao->select('*')->from(TABLE_USER)
->where('account')->eq($account)
//->beginIF(strlen($password) < 32)->andWhere('password')->eq(md5($password))->fi()
//->andWhere('deleted')->eq(0)
->fetch();
/* If the length of $password is 32 or 40, checking by the auth hash. */
$user = false;
if($record)
{
//echo "<script> alert('Get user info success'); </script> ";
$passwordLength = strlen($password);
if($passwordLength < 32)
{
$user = $record;
}
elseif($passwordLength == 32)
{
$hash = $this->session->rand ? md5($record->password . $this->session->rand) : $record->password;
$user = $password == $hash ? $record : '';
}
elseif($passwordLength == 40)
{
$hash = sha1($record->account . $record->password . $record->last);
$user = $password == $hash ? $record : '';
}
}else{
//echo "<script> alert('Get user info failed'); </script> ";
}
if($user)
{
//echo "<script> alert('Update user login info'); </script> ";
$ip = $this->server->remote_addr;
$last = $this->server->request_time;
$this->dao->update(TABLE_USER)->set('visits = visits + 1')->set('ip')->eq($ip)->set('last')->eq($last)->where('account')->eq($account)->exec();
$user->last = date(DT_DATETIME1, $user->last);
}
return $user;
}




精品资料包
1V1产品演示
免费试用增强功能
专属顾问答疑支持


