discuz社区与java web的钉钉手机版整合(一)

在前面的博文中,我已经完成了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


加上代码后,就可以用url访问:http://localhost/member.php?mod=logging&action=login&app=ding&ding_uid=9

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.自己组合代码。

。。。。。。(未完待续)



你可能感兴趣的:(discuz社区与java web的钉钉手机版整合(一))