譴責下某位同學,轉載了我的上一篇文章,也不給個原文地址,希望這次再來轉時能加上。
//檢查登入,在common.php判斷
//cookie串: 2|dc4fab5bb354be5104bae0affe2c1b615c565cf5|1384165106|eb084e693bb241a29e9986b62e69cf5f465f354d
//cookie有效期大於當前時間=》繼續判斷:使用者cookie中儲存的使用者ID、生存週期、及預設定的cookie金鑰,經過特殊處理後與$cookie['cookie_hash']比較
1 function check_cookie(&$pun_user) 2 { 3 global $db, $db_type, $pun_config, $cookie_name, $cookie_seed; 4 5 $now = time(); 6 7 // If the cookie is set and it matches the correct pattern, then read the values from it 8 if (isset($_COOKIE[$cookie_name]) && preg_match('%^(\d+)\|([0-9a-fA-F]+)\|(\d+)\|([0-9a-fA-F]+)$%', $_COOKIE[$cookie_name], $matches)) 9 { 10 $cookie = array( 11 'user_id' => intval($matches[1]), 12 'password_hash' => $matches[2], 13 'expiration_time' => intval($matches[3]), 14 'cookie_hash' => $matches[4], 15 ); 16 } 17 18 // If it has a non-guest user, and hasn't expired 19 if (isset($cookie) && $cookie['user_id'] > 1 && $cookie['expiration_time'] > $now) 20 { 21 // If the cookie has been tampered with 22 if (forum_hmac($cookie['user_id'].'|'.$cookie['expiration_time'], $cookie_seed.'_cookie_hash') != $cookie['cookie_hash']) 23 { 24 $expire = $now + 31536000; // The cookie expires after a year 25 pun_setcookie(1, pun_hash(uniqid(rand(), true)), $expire); 26 set_default_user(); 27 28 return; 29 } 30 ...............
//從上面得到的$cookie變數中的user_id,去資料庫查詢取到密碼,特殊處理後與$cookie中的password_hash比較
1 // Check if there's a user with the user ID and password hash from the cookie 2 $result = $db->query('SELECT u.*, g.*, o.logged, o.idle FROM '.$db->prefix.'users AS u INNER JOIN '.$db->prefix.'groups AS g ON u.group_id=g.g_id LEFT JOIN '.$db->prefix.'online AS o ON o.user_id=u.id WHERE u.id='.intval($cookie['user_id'])) or error('Unable to fetch user information', __FILE__, __LINE__, $db->error()); 3 $pun_user = $db->fetch_assoc($result); 4 5 // If user authorisation failed 6 if (!isset($pun_user['id']) || forum_hmac($pun_user['password'], $cookie_seed.'_password_hash') !== $cookie['password_hash']) 7 { 8 $expire = $now + 31536000; // The cookie expires after a year 9 pun_setcookie(1, pun_hash(uniqid(rand(), true)), $expire); 10 set_default_user(); 11 12 return; 13 }
//退出 "login.php?action=out&id=2&csrf_token=40ce5abbaf76ba6fe66bb8a833eb9e8d4da5c273" ,此處沒有直接刪除cookie
//先判斷使用者是否已登入,連結是否有相應的標識
1 if ($action == 'out') 2 { 3 if ($pun_user['is_guest'] || !isset($_GET['id']) || $_GET['id'] != $pun_user['id'] || !isset($_GET['csrf_token']) || $_GET['csrf_token'] != pun_hash($pun_user['id'].pun_hash(get_remote_address()))) 4 { 5 header('Location: index.php'); 6 exit; 7 } 8 9 // Remove user from "users online" list 10 $db->query('DELETE FROM '.$db->prefix.'online WHERE user_id='.$pun_user['id']) or error('Unable to delete from online list', __FILE__, __LINE__, $db->error()); 11 12 // Update last_visit (make sure there's something to update it with) 13 if (isset($pun_user['logged'])) 14 $db->query('UPDATE '.$db->prefix.'users SET last_visit='.$pun_user['logged'].' WHERE id='.$pun_user['id']) or error('Unable to update user visit data', __FILE__, __LINE__, $db->error()); 15 16 pun_setcookie(1, pun_hash(uniqid(rand(), true)), time() + 31536000); 17 18 redirect('index.php', $lang_login['Logout redirect']); 19 }
//get_remote_address()取遠端IP,區分了是否用了代理
1 function get_remote_address() 2 { 3 $remote_addr = $_SERVER['REMOTE_ADDR']; 4 5 // If we are behind a reverse proxy try to find the real users IP 6 if (defined('FORUM_BEHIND_REVERSE_PROXY')) 7 { 8 if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) 9 { 10 // The general format of the field is: 11 // X-Forwarded-For: client1, proxy1, proxy2 12 // where the value is a comma+space separated list of IP addresses, the left-most being the farthest downstream client, 13 // and each successive proxy that passed the request adding the IP address where it received the request from. 14 $forwarded_for = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']); 15 $forwarded_for = trim($forwarded_for[0]); 16 17 if (@preg_match('%^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$%', $forwarded_for) || @preg_match('%^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$%', $forwarded_for)) 18 $remote_addr = $forwarded_for; 19 } 20 } 21 22 return $remote_addr; 23 }
//退出時cookie處理
1 pun_setcookie(1, pun_hash(uniqid(rand(), true)), time() + 31536000);
1 // Set a cookie, FluxBB style! 2 // Wrapper for forum_setcookie 3 // 4 function pun_setcookie($user_id, $password_hash, $expire) 5 { 6 global $cookie_name, $cookie_seed; 7 8 forum_setcookie($cookie_name, $user_id.'|'.forum_hmac($password_hash, $cookie_seed.'_password_hash').'|'.$expire.'|'.forum_hmac($user_id.'|'.$expire, $cookie_seed.'_cookie_hash'), $expire); 9 } 10 11 12 // 13 // Set a cookie, FluxBB style! 14 // 15 function forum_setcookie($name, $value, $expire) 16 { 17 global $cookie_path, $cookie_domain, $cookie_secure, $pun_config; 18 19 if ($expire - time() - $pun_config['o_timeout_visit'] < 1) 20 $expire = 0; 21 22 // Enable sending of a P3P header 23 header('P3P: CP="CUR ADM"'); 24 25 if (version_compare(PHP_VERSION, '5.2.0', '>=')) 26 setcookie($name, $value, $expire, $cookie_path, $cookie_domain, $cookie_secure, true); 27 else 28 setcookie($name, $value, $expire, $cookie_path.'; HttpOnly', $cookie_domain, $cookie_secure); 29 }
//定義一些通用函式,
如:error():
error('Unable to fetch user info', __FILE__, __LINE__, $db->error())
message($message, $no_back_link = false, $http_status = null)
utf8_trim( $str, $charlist=false); //去空格
redirect($destination_url, $message); //重定向
fluxbb多數頁面都寫在一個檔案中,如login.php包括登入、退出、忘記密碼等操作,通過不同的action區分。
引入公用header.php、不同頁面分別替換相應的內容($pun_user變數),如title、要載入的css等。
$pun_user變數前面提到的check_cookie()函式中設定的值。
1 $pun_user = array(); 2 check_cookie($pun_user);
function check_cookie(&$pun_user){} //注意後面的&地址符
check_cookie(函式中,通過cookie值來判斷使用者資訊,如是合法的已登入使用者,直接將一些值儲存到$pun_user,否則設定一些預設值。通過set_default_user()函式,並記錄線上使用者。
1 // 2 // Fill $pun_user with default values (for guests) 3 // 4 function set_default_user() 5 { 6 global $db, $db_type, $pun_user, $pun_config; 7 8 $remote_addr = get_remote_address(); 9 10 // Fetch guest user 11 $result = $db->query('SELECT u.*, g.*, o.logged, o.last_post, o.last_search FROM '.$db->prefix.'users AS u INNER JOIN '.$db->prefix.'groups AS g ON u.group_id=g.g_id LEFT JOIN '.$db->prefix.'online AS o ON o.ident=\''.$db->escape($remote_addr).'\' WHERE u.id=1') or error('Unable to fetch guest information', __FILE__, __LINE__, $db->error()); 12 if (!$db->num_rows($result)) 13 exit('Unable to fetch guest information. Your database must contain both a guest user and a guest user group.'); 14 15 $pun_user = $db->fetch_assoc($result); 16 17 // Update online list 18 if (!$pun_user['logged']) 19 { 20 $pun_user['logged'] = time(); 21 22 // With MySQL/MySQLi/SQLite, REPLACE INTO avoids a user having two rows in the online table 23 switch ($db_type) 24 { 25 case 'mysql': 26 case 'mysqli': 27 case 'mysql_innodb': 28 case 'mysqli_innodb': 29 case 'sqlite': 30 $db->query('REPLACE INTO '.$db->prefix.'online (user_id, ident, logged) VALUES(1, \''.$db->escape($remote_addr).'\', '.$pun_user['logged'].')') or error('Unable to insert into online list', __FILE__, __LINE__, $db->error()); 31 break; 32 33 default: 34 $db->query('INSERT INTO '.$db->prefix.'online (user_id, ident, logged) SELECT 1, \''.$db->escape($remote_addr).'\', '.$pun_user['logged'].' WHERE NOT EXISTS (SELECT 1 FROM '.$db->prefix.'online WHERE ident=\''.$db->escape($remote_addr).'\')') or error('Unable to insert into online list', __FILE__, __LINE__, $db->error()); 35 break; 36 } 37 } 38 else 39 $db->query('UPDATE '.$db->prefix.'online SET logged='.time().' WHERE ident=\''.$db->escape($remote_addr).'\'') or error('Unable to update online list', __FILE__, __LINE__, $db->error()); 40 41 $pun_user['disp_topics'] = $pun_config['o_disp_topics_default']; 42 $pun_user['disp_posts'] = $pun_config['o_disp_posts_default']; 43 $pun_user['timezone'] = $pun_config['o_default_timezone']; 44 $pun_user['dst'] = $pun_config['o_default_dst']; 45 $pun_user['language'] = $pun_config['o_default_lang']; 46 $pun_user['style'] = $pun_config['o_default_style']; 47 $pun_user['is_guest'] = true; 48 $pun_user['is_admmod'] = false; 49 }
//footer.php
頁面header和footer內容通過$tpl_main變數儲存,footer.php最後,exit($tpl_main);直接輸出並終止執行。主要用到了輸出緩衝的一些函式。
在整個fluxbb系統中,只看到了兩個js檔案,分別是common.js和minmax.js,而且兩個檔案都沒超過3kb,其中minmax.js是在header.php引入了。想想自己,沒有jquery就有點寸步難行了。
原文作者:lltong,部落格園地址:http://www.cnblogs.com/lltong/