81209

发一个支持openldap (SSHA方式加密)的扩展

回帖
回帖数 2
阅读数 6807
发表时间 2012-05-31 20:49:22
🍟
刘达楼主

今天用了整一天的时间尝试为禅道加上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;

}

2个回复
🍟
刘达沙发
有一个问题,由于这个玩意是在用户登录的时候去同步LDAP用户数据到禅道数据库里,所以同步机制是不完整的,比如在LDAP服务器上删除一个用户,禅道数据库里的用户信息不会被删除,当然这个账号也登录不了了。有个思路是使用定时任务去同步LDAP服务器,然后把上面代码里往数据库里新加用户的代码去掉,后面有时间研究一下。
2012-05-31 21:02:10 刘达 回帖
🍟
春哥板凳
感谢分享。:)
2012-06-01 07:56:31 王春生 回帖
联系我们
联系人
刘斌/高级客户经理
电话(微信)
17685869372
QQ号码
526288068
联系邮箱
liubin@chandao.com
相关帖子
返回顶部
客服头像
刘斌
高级客户经理
客服微信
17685869372
526288068
统一服务热线 4006-8899-23
我要提问提问有任何问题,您都可以在这里提问。问题反馈反馈点击这里,让我们聆听您的建议与反馈。