天天看點

Discuz UCenter Server功能解析

技術點

1.extract函數

将清單中的存在映射關系的key建立為變量,value作為變量值。具體可看:https://secure.php.net/manual/en/function.extract.php。

2.explode函數

分割字元串,相當于Java或者Python中的split。

3.sid包含使用者名資訊

登入UCenter之後,頁面的連結顯示為:/uc_server/admin.php?sid=c935ichRGUiM9%2BuTj3o%2BE4h9towLwM9iSFMM0%2BV0GB7hDtoQCCOilLv99TMU7IoI5yfrccjEZ54C0w,其中sid包含了使用者名和check碼,check碼與浏覽器UserAgent相關,解密代碼為:

function sid_decode($sid) {
		$ip = $this->onlineip;
		$agent = $_SERVER['HTTP_USER_AGENT'];
		$authkey = md5($ip.$agent.UC_KEY);
		$s = $this->authcode(rawurldecode($sid), 'DECODE', $authkey, 1800);
		if(empty($s)) {
			return FALSE;
		}
		@list($username, $check) = explode("\t", $s);
		if($check == substr(md5($ip.$agent), 0, 8)) {
			return $username;
		} else {
			return FALSE;
		}
	}
           

4.eval函數

對字元串内的變量進行解析,例如:

<?php
$string = 'cup';
$name = 'coffee';
$str = 'This is a $string with my $name in it.';
echo $str. "\n";
eval("\$str = \"$str\";");
echo $str. "\n";
?>
           

輸出為:

This is a $string with my $name in it.

This is a cup with my coffee in it.

5.register_shutdown_function函數

<?php
function shutdown()
{
    // This is our shutdown function, in 
    // here we can do any last operations
    // before the script is complete.

    echo 'Script executed with success', PHP_EOL;
}

register_shutdown_function('shutdown');
?>
           

6.unlink函數

删除一個檔案名,有可能删除這個檔案名指向的檔案。

功能

discuz ucenter server采用經典MVC(即Model、View、Controller)的代碼架構,如下圖所示。Model層實作了資料庫及緩存等功能,View層實作了各種模闆,Controller層則負責所有的業務邏輯,從Model層擷取資料并對View進行渲染,輸出給使用者。

Discuz UCenter Server功能解析

下面我們分析一下UCenter背景幾個比較特殊的功能子產品:

資料備份

discuz ucenter有資料備份和資料恢複功能,都是針對資料庫的。資料備份的主要功能實作在api/dbbak.php的sqldumptablestruct和sqldumptable函數中,最終将資料庫以sql語句的方式導出到data/backup檔案夾的.sql檔案中。

導出資料庫表結構可以通過執行下面的sql語句導出:

導出數表資料則先導出列字段,再根據資料類型批量導出資料:

将字元和文本類型的資料導出為16進制的hex碼,其他類型直接轉化為字元串:

最終備份輸出的檔案内容如下:

# Identify: MTU1MjI5NzU3NSx1Y2VudGVyLHVjZW50ZXIsbXVsdGl2b2wsMQ==
# <?php exit();?>
# ucenter Multi-Volume Data Dump Vol.1
# Time: 2019-03-11 17:46:15
# Type: ucenter
# Table Prefix: dcz_ucenter_
# utf8
# ucenter Home: http://www.comsenz.com
# Please visit our website for newest infomation about ucenter
# --------------------------------------------------------


DROP TABLE IF EXISTS dcz_ucenter_admins;
CREATE TABLE dcz_ucenter_admins (
  uid mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
  username char(15) NOT NULL DEFAULT '',
  allowadminsetting tinyint(1) NOT NULL DEFAULT 0,
  allowadminapp tinyint(1) NOT NULL DEFAULT 0,
  allowadminuser tinyint(1) NOT NULL DEFAULT 0,
  allowadminbadword tinyint(1) NOT NULL DEFAULT 0,
  allowadmintag tinyint(1) NOT NULL DEFAULT 0,
  allowadminpm tinyint(1) NOT NULL DEFAULT 0,
  allowadmincredits tinyint(1) NOT NULL DEFAULT 0,
  allowadmindomain tinyint(1) NOT NULL DEFAULT 0,
  allowadmindb tinyint(1) NOT NULL DEFAULT 0,
  allowadminnote tinyint(1) NOT NULL DEFAULT 0,
  allowadmincache tinyint(1) NOT NULL DEFAULT 0,
  allowadminlog tinyint(1) NOT NULL DEFAULT 0,
  PRIMARY KEY (uid),
  UNIQUE KEY username (username)
) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 AUTO_INCREMENT=2;

......

INSERT INTO dcz_ucenter_admins VALUES ('1',0x61646d696e,'1','1','1','1','1','1','1','1','1','1','1','1');
......
           

恢複資料就比較好了解了,就是直接執行這個備份檔案,對資料庫進行重建。恢複千萬條,謹慎第一條,操作不規範,老闆兩行淚。

更新緩存

更新緩存的功能實作在cachemodel中,分為更新資料緩存功能和更新模闆緩存功能。

更新資料緩存的清單由map變量決定:

$this->map = array(
	'settings' => array('settings'),
	'badwords' => array('badwords'),
	'plugins' => array('plugins'),
	'apps' => array('apps'),
);
           

分别是更新設定、不良詞語、插件和APP清單。APP清單緩存的更新是通過調用appmodel的get_apps方法從資料庫中擷取APP清單,然後将清單緩存到檔案data/cache/apps.php中,下次要擷取APP清單直接require該緩存檔案就可以了,不需要再從資料庫讀取。apps.php檔案的内容為:

<?php
$_CACHE['apps'] = array (
  1 => 
  array (
    'appid' => '1',
    'type' => 'DISCUZX',
    'name' => 'Discuz! Board',
    'url' => 'http://127.0.0.1',
    'authkey' => 'o7y2z1J7rbd1O0Aaj2EcO4A8r9ca6cA99c5902ib23e3S3n6w2G0yfSfl7lcy9Re',
    'ip' => '',
    'viewprourl' => '',
    'apifilename' => 'uc.php',
    'charset' => '',
    'dbcharset' => '',
    'synlogin' => '1',
    'recvnote' => '1',
    'extra' => '',
    'tagtemplates' => '',
    'allowips' => '',
  ),
);

?>
           

更新模闆緩存則是将data/view/目錄下的所有緩存檔案删除,以便下次使用者通路時生成新的緩存檔案。緩存檔案則是由template(lib/template.class.php)在編譯模闆檔案之後儲存的。

檢驗檔案

這一塊功能涉及discuz的插件功能。檢驗檔案功能就是一個插件,它用于驗證UCenter項目本身檔案的完整性。插件存放在plugin/目錄下,檢驗檔案的插件目錄為plugin/filecheck/。在使用者通路插件功能時,會先require control/admin/plugin.php檔案,這個檔案内會查找目标插件并引用,相關代碼如下:

if(!@require_once UC_ROOT."./plugin/$a/plugin.php") {
	exit('Plugin not found');
}

           

最後調用通過調用插件類的方法執行插件功能。檢驗檔案功能的實作是通過實作儲存的檔案md5值與現有檔案的md5值進行比較然後統計出來的,其中被修改數指的是被修改過的檔案的數量,不包括新增和删除,而一周内被修改則包括新增和删除的檔案。