在前面的博文中,我已经完成了discuz与java web在浏览器上的整合,大概原理是利用ucernter作为中介,在java web中登录时,调用uc_user_login()登录,这时候就会返回一段js代码把cookie写在浏览器中,使得两个系统公用相同的cookie以达到同步登录的目的。
我们都知道,很多公司都用使用阿里的钉钉作为办公通讯工具。那么这篇将介绍如何使用融合discuz,java web,钉钉的同步登录!
一、首先先看看钉钉与discuz的整合:
由于钉钉的微应用是根据url去访问的,所以原理是:在url给discuz传送key值和uid的值,discuz服务端在获取key值后知道是钉钉应用的访问,再根据uid判断是哪位用户登录。那么我们需要做的是
1.如何绕开discuz的登录验证。
首先,我们先了解discuz的源码目录框架,在上一篇我转载了别人介绍的目录框架。找到根目录的menber代码:
<?php /** * [Discuz!] (C)2001-2099 Comsenz Inc. * This is NOT a freeware, use is subject to license terms * * $Id: member.php 24411 2011-09-19 05:09:03Z monkey $ */ define('APPTYPEID', 0); define('CURSCRIPT', 'member'); require './source/class/class_core.php'; $discuz = C::app(); $modarray = array('activate', 'clearcookies', 'emailverify', 'getpasswd', 'groupexpiry', 'logging', 'lostpasswd', 'register', 'regverify', 'switchstatus'); $mod = !in_array($discuz->var['mod'], $modarray) && (!preg_match('/^\w+$/', $discuz->var['mod']) || !file_exists(DISCUZ_ROOT.'./source/module/member/member_'.$discuz->var['mod'].'.php')) ? 'register' : $discuz->var['mod']; define('CURMODULE', $mod); $discuz->init(); if($mod == 'register' && $discuz->var['mod'] != $_G['setting']['regname']) { showmessage('undefined_action'); } require libfile('function/member'); require libfile('class/member'); runhooks(); require DISCUZ_ROOT.'./source/module/member/member_'.$mod.'.php'; ?>粗略地阅读代码,我们发觉,他是根据mod值来判断用户的操作是login,并且引入function/member,class/class_member和/source/module/member/member_ligin.php。于是我们找啊找,确定class_member.php的on_login()函数是用来处理登录的函数。问题来了,这一大 篇幅的东东怎样知道他如何运行?这里我有一个小技巧:利用showmessage()函数来作为断点判断它运行到哪一步,这样就能很好地了解它的运行逻辑了。代码如下:自己对比源代码(discuzX2.5)找亮点
function on_login() { global $_G; if($_G['uid']) { $referer = dreferer(); $ucsynlogin = $this->setting['allowsynlogin'] ? uc_user_synlogin($_G['uid']) : ''; $param = array('username' => $_G['member']['username'], 'usergroup' => $_G['group']['grouptitle'], 'uid' => $_G['member']['uid']); showmessage('login_succeed', $referer ? $referer : './', $param, array('showdialog' => 1, 'locationtime' => true, 'extrajs' => $ucsynlogin)); } $from_connect = $this->setting['connect']['allow'] && !empty($_GET['from']) ? 1 : 0; $seccodecheck = $from_connect ? false : $this->setting['seccodestatus'] & 2; $seccodestatus = !empty($_GET['lssubmit']) ? false : $seccodecheck; $invite = getinvite(); //1. edit && $_GET['app'] != "ding" if(!submitcheck('loginsubmit', 1, $seccodestatus) && $_GET['app'] != "ding") { //showmessage("11111");//-------------------------------------------- $auth = ''; $username = !empty($_G['cookie']['loginuser']) ? dhtmlspecialchars($_G['cookie']['loginuser']) : ''; if(!empty($_GET['auth'])) { list($username, $password, $questionexist) = explode("\t", authcode($_GET['auth'], 'DECODE')); $username = dhtmlspecialchars($username); $auth = dhtmlspecialchars($_GET['auth']); } $cookietimecheck = !empty($_G['cookie']['cookietime']) || !empty($_GET['cookietime']) ? 'checked="checked"' : ''; if($seccodecheck) { $seccode = random(6, 1) + $seccode{0} * 1000000; } if($this->extrafile && file_exists($this->extrafile)) { require_once $this->extrafile; } $navtitle = lang('core', 'title_login'); include template($this->template); } else { <span style="color:#ff0000;">//钉钉登录的处理函数在这里---------------------------------------------- if($_GET['app'] == "ding" && $_GET['ding_uid'] > 0){ //showmessage("into1");//-------------------------------------------- $result = userlogin1($_GET['ding_uid']); }else { // 如果不是</span> if(!empty($_GET['auth'])) { list($_GET['username'], $_GET['password']) = daddslashes(explode("\t", authcode($_GET['auth'], 'DECODE'))); } if(!($_G['member_loginperm'] = logincheck($_GET['username']))) { showmessage('login_strike'); } if($_GET['fastloginfield']) { $_GET['loginfield'] = $_GET['fastloginfield']; } $_G['uid'] = $_G['member']['uid'] = 0; $_G['username'] = $_G['member']['username'] = $_G['member']['password'] = ''; if(!$_GET['password'] || $_GET['password'] != addslashes($_GET['password'])) { showmessage('profile_passwd_illegal'); } $result = userlogin($_GET['username'], $_GET['password'], $_GET['questionid'], $_GET['answer'], $this->setting['autoidselect'] ? 'auto' : $_GET['loginfield'], $_G['clientip']); } // end else $uid = $result['ucresult']['uid']; if(!empty($_GET['lssubmit']) && ($result['ucresult']['uid'] == -3 || $seccodecheck)) { $_GET['username'] = $result['ucresult']['username']; $this->logging_more($result['ucresult']['uid'] == -3); } if($result['status'] == -1) { if(!$this->setting['fastactivation']) { $auth = authcode($result['ucresult']['username']."\t".FORMHASH, 'ENCODE'); showmessage('location_activation', 'member.php?mod='.$this->setting['regname'].'&action=activation&auth='.rawurlencode($auth).'&referer='.rawurlencode(dreferer()), array(), array('location' => true)); } else { $init_arr = explode(',', $this->setting['initcredits']); $groupid = $this->setting['regverify'] ? 8 : $this->setting['newusergroupid']; C::t('common_member')->insert($uid, $result['ucresult']['username'], md5(random(10)), $result['ucresult']['email'], $_G['clientip'], $groupid, $init_arr); $result['member'] = getuserbyuid($uid); $result['status'] = 1; } } if($result['status'] > 0) { //showmessage("1111111111");//-------------------------------------------------------- if($this->extrafile && file_exists($this->extrafile)) { require_once $this->extrafile; } setloginstatus($result['member'], $_GET['cookietime'] ? 2592000 : 0); checkfollowfeed(); if($_G['member']['lastip'] && $_G['member']['lastvisit']) { dsetcookie('lip', $_G['member']['lastip'].','.$_G['member']['lastvisit']); } C::t('common_member_status')->update($_G['uid'], array('lastip' => $_G['clientip'], 'lastvisit' =>TIMESTAMP, 'lastactivity' => TIMESTAMP)); $ucsynlogin = $this->setting['allowsynlogin'] ? uc_user_synlogin($_G['uid']) : ''; if($invite['id']) { $result = C::t('common_invite')->count_by_uid_fuid($invite['uid'], $uid); if(!$result) { C::t('common_invite')->update($invite['id'], array('fuid'=>$uid, 'fusername'=>$_G['username'])); updatestat('invite'); } else { $invite = array(); } } if($invite['uid']) { require_once libfile('function/friend'); friend_make($invite['uid'], $invite['username'], false); dsetcookie('invite_auth', ''); if($invite['appid']) { updatestat('appinvite'); } } $param = array( 'username' => $result['ucresult']['username'], 'usergroup' => $_G['group']['grouptitle'], 'uid' => $_G['member']['uid'], 'groupid' => $_G['groupid'], 'syn' => $ucsynlogin ? 1 : 0 ); $extra = array( 'showdialog' => true, 'locationtime' => true, 'extrajs' => $ucsynlogin ); $loginmessage = $_G['groupid'] == 8 ? 'login_succeed_inactive_member' : 'login_succeed'; $location = $invite || $_G['groupid'] == 8 ? 'home.php?mod=space&do=home' : dreferer(); if(empty($_GET['handlekey']) || !empty($_GET['lssubmit'])) { if(defined('IN_MOBILE')) { showmessage($loginmessage, $location, $param, array('location' => true)); } else { if(!empty($_GET['lssubmit'])) { if(!$ucsynlogin) { $extra['location'] = true; } showmessage($loginmessage, $location, $param, $extra); } else { $href = str_replace("'", "\'", $location); showmessage('location_login_succeed', $location, array(), array( 'showid' => 'succeedmessage', 'extrajs' => '<script type="text/javascript">'. 'setTimeout("window.location.href =\''.$href.'\';", 3000);'. '$(\'succeedmessage_href\').href = \''.$href.'\';'. '$(\'main_message\').style.display = \'none\';'. '$(\'main_succeed\').style.display = \'\';'. '$(\'succeedlocation\').innerHTML = \''.lang('message', $loginmessage, $param).'\';</script>'.$ucsynlogin, 'striptags' => false, 'showdialog' => true ) ); } } } else { showmessage($loginmessage, $location, $param, $extra); } } else { $password = preg_replace("/^(.{".round(strlen($_GET['password']) / 4)."})(.+?)(.{".round(strlen($_GET['password']) / 6)."})$/s", "\\1***\\3", $_GET['password']); $errorlog = dhtmlspecialchars( TIMESTAMP."\t". ($result['ucresult']['username'] ? $result['ucresult']['username'] : $_GET['username'])."\t". $password."\t". "Ques #".intval($_GET['questionid'])."\t". $_G['clientip']); writelog('illegallog', $errorlog); loginfailed($_GET['username']); $fmsg = $result['ucresult']['uid'] == '-3' ? (empty($_GET['questionid']) || $answer == '' ? 'login_question_empty' : 'login_question_invalid') : 'login_invalid'; if($_G['member_loginperm'] > 1) { showmessage($fmsg, '', array('loginperm' => $_G['member_loginperm'] - 1)); } elseif($_G['member_loginperm'] == -1) { showmessage('login_password_invalid'); } else { showmessage('login_strike'); } } } }
然后 在function的的function/function_menber.php中根据userlogin()的代码加入钉钉认证的userlogin1()
//钉钉认证 function userlogin1($uid) { $return = array(); $member = getuserbyuid($uid, 1); $return['member'] = $member; $return['status'] = 1; return $return; } //end
ok!在浏览器直接输入url,成功登陆,退出再登录,成功!(注意:每次都要退出后再登录)
2.如何绕开discuz的登录验证(根据discuz用户账号)。
上面的1用uid来绕开很方便,用username绕开好像也不难(前提是你熟悉discuz的数据库操作机制)。因为钉钉的接口获取的是username的值(下一篇会讲),所以这里需要根据username来绕开登录验证。于是去找getuserbyusername()的函数,你会发觉找不到,首先这个函数是一开始的时候就通过function_core.php中加载的,在这个函数中却没有getuserbyusername这个函数,于是乎想自己写,但是自己不熟悉php(本人是java程序猿)。耗了很久时间才搞懂里面C::t('common_member_archive')>fetch($uid);意思是从/source/class/table文件夹内的table_common_member_archive.php里面提取fetch的函数。于是乎根据表来找,我们要获取用户的数据,那么就应该通过table_common_member.php这个函数,很惊奇地就会发现里面有fetch_by_username()函数于是乎,一切都迎刃而解!!
总结:
1.C::t('common_member_archive')>fetch($uid);意思是从/source/class/table文件夹内的table_common_member_archive.php里面提取fetch的函数
2.区table_common_member.php这个函数找相关函数
3.自己组合代码。
。。。。。。(未完待续)