Discuz x3.5 核心文件 function/function_member.php 函数注释
New
- <?php /** * [Discuz!] (C)2001-2099 Comsenz Inc. * This is NOT a freeware, use is subject to license terms * * $Id: function_member.php 35030 2014-10-23 07:43:23Z laoguozhang $ */ if(!defined('IN_DISCUZ')) { exit('Access Denied');}/** * 用户登录函数 * * @param string $username 用户名、UID、邮箱或安全手机号 * @param string $password 用户密码 * @param int $questionid 安全问题ID(暂未使用) * @param string $answer 安全问题答案(暂未使用) * @param string $loginfield 登录方式标识,默认为'username',可选'uid'、'email'、'auto'、'secmobile' * @param string $ip 用户登录的IP地址,默认为空 * [url=home.php?mod=space&uid=33239]@return[/url] array 返回登录结果,包括状态(status)、用户信息(member)和UC登录结果(ucresult) */function userlogin($username, $password, $questionid, $answer, $loginfield = 'username', $ip = '') { $return = array(); // 根据登录字段确定登录类型 if($loginfield == 'uid' && getglobal('setting/uidlogin')) { $isuid = 1; } elseif($loginfield == 'email') { $isuid = 2; } elseif($loginfield == 'auto') { $isuid = 3; } elseif($loginfield == 'secmobile' && getglobal('setting/secmobilelogin')) { $isuid = 4; } else { $isuid = 0; } // 加载UCenter通信函数,如未定义则先加载 if(!function_exists('uc_user_login')) { loaducenter(); } // 处理自动登录逻辑 if($isuid == 3) { // 根据用户名尝试登录,支持UID、邮箱和安全手机号 if(!strcmp(dintval($username), $username) && getglobal('setting/uidlogin')) { $return['ucresult'] = uc_user_login($username, $password, 1, 1, $questionid, $answer, $ip, 1); } elseif(isemail($username)) { $return['ucresult'] = uc_user_login($username, $password, 2, 1, $questionid, $answer, $ip, 1); } elseif(preg_match('/^(\d{1,12}|\d{1,3}-\d{1,12})$/', $username) && getglobal('setting/secmobilelogin')) { $username = strpos($username, '-') === false ? (getglobal('setting/smsdefaultcc') . '-' . $username) : $username; $return['ucresult'] = uc_user_login($username, $password, 4, 1, $questionid, $answer, $ip, 1); } // 如果登录失败且不是因为账户不存在,则尝试使用用户名密码登录 if($return['ucresult'][0] <= 0 && $return['ucresult'][0] != -3) { $return['ucresult'] = uc_user_login(addslashes($username), $password, 0, 1, $questionid, $answer, $ip); } } else { // 处理非自动登录类型 if($isuid == 4) { $username = strpos($username, '-') === false ? (getglobal('setting/smsdefaultcc') . '-' . $username) : $username; } $return['ucresult'] = uc_user_login(addslashes($username), $password, $isuid, 1, $questionid, $answer, $ip); } // 解析UC登录结果 $tmp = array(); $duplicate = ''; list($tmp['uid'], $tmp['username'], $tmp['password'], $tmp['email'], $duplicate) = $return['ucresult']; $return['ucresult'] = $tmp; // 检查登录结果,登录失败或用户数据重复则返回 if($duplicate && $return['ucresult']['uid'] > 0 || $return['ucresult']['uid'] <= 0) { $return['status'] = 0; return $return; } // 获取用户详细信息 $member = getuserbyuid($return['ucresult']['uid'], 1); if(!$member || empty($member['uid'])) { $return['status'] = -1; return $return; } $return['member'] = $member; // 登录成功 $return['status'] = 1; if($member['_inarchive']) { // 如果用户是归档用户,则将其移回主表 C::t('common_member_archive')->move_to_master($member['uid']); } // 更新用户邮箱,解决可能的邮箱变更问题 if($member['email'] != $return['ucresult']['email']) { C::t('common_member')->update($return['ucresult']['uid'], array('email' => $return['ucresult']['email'])); } return $return;}/** * 设置登录状态 * * 用于在用户成功登录后,设置用户的登录状态,包括但不限于用户ID、用户名、管理员等级、用户组等信息, * 同时更新会话信息、设置登录相关的cookie,以及更新统计信息。 * * @param array $member 包含用户登录信息的数组,至少应包含uid、username、adminid、groupid等字段 * @param int $cookietime 登录cookie的有效时间,单位为秒 */function setloginstatus($member, $cookietime) { global $_G; $_G['uid'] = intval($member['uid']); $_G['username'] = $member['username']; $_G['adminid'] = $member['adminid']; $_G['groupid'] = $member['groupid']; $_G['formhash'] = formhash(); $_G['session']['invisible'] = getuserprofile('invisible'); $_G['member'] = $member; loadcache('usergroup_'.$_G['groupid']); C::app()->session->isnew = true; C::app()->session->updatesession(); // 设置登录认证cookie dsetcookie('auth', authcode("{$member['password']}\t{$member['uid']}", 'ENCODE'), $cookietime, 1, true); dsetcookie('loginuser'); dsetcookie('activationauth'); dsetcookie('pmnum'); // 更新登录统计信息 include_once libfile('function/stat'); updatestat('login', 1); if(defined('IN_MOBILE')) { updatestat('mobilelogin', 1); } if($_G['setting']['connect']['allow'] && $_G['member']['conisbind']) { updatestat('connectlogin', 1); } // 更新用户积分 $rule = updatecreditbyaction('daylogin', $_G['uid']); if(!$rule['updatecredit']) { checkusergroup($_G['uid']); }} /** * 登录检查 * * 用于检查用户登录名是否可用,如果是,则返回可以登录的标志;如果不可用,根据失败次数返回相应的延迟时间。 * * @param string $username 用户输入的用户名 * @return int 返回值为0表示可以登录,大于0表示需要等待的时间(秒) */function logincheck($username) { global $_G; $return = 0; $username = trim($username); loaducenter(); if(function_exists('uc_user_logincheck')) { // 如果存在与UCenter的登录检查函数,则调用UCenter的登录检查 $return = uc_user_logincheck(addslashes($username), $_G['clientip']); } else { // 不存在时,进行本地登录检查 $login = C::t('common_failedlogin')->fetch_ip($_G['clientip']); $return = (!$login || (TIMESTAMP - $login['lastupdate'] > 900)) ? 5 : max(0, 5 - $login['count']); if(!$login) { C::t('common_failedlogin')->insert(array( 'ip' => $_G['clientip'], 'count' => 0, 'lastupdate' => TIMESTAMP ), false, true); } elseif(TIMESTAMP - $login['lastupdate'] > 900) { C::t('common_failedlogin')->insert(array( 'ip' => $_G['clientip'], 'count' => 0, 'lastupdate' => TIMESTAMP ), false, true); C::t('common_failedlogin')->delete_old(901); } } return $return;} /** * 登录失败处理 * * 当用户登录失败时,记录登录失败信息,防止恶意登录攻击。 * * @param string $username 用户输入的用户名 */function loginfailed($username) { global $_G; loaducenter(); if(function_exists('uc_user_logincheck')) { // 如果存在与UCenter的登录检查函数,则不进行处理 return; } // 记录登录失败信息 C::t('common_failedlogin')->update_failed($_G['clientip']);}/** * 检查IP尝试次数是否超过限制。 * * @param $numiptry int 尝试次数限制。 * @param $timeiptry int 时间限制(秒)。超过此时间限制,尝试次数将被重置。 * @return bool 如果尝试次数超过限制,返回true;否则,返回false。 */function failedipcheck($numiptry, $timeiptry) { global $_G; if(!$numiptry) { return false; } // 检查当前IP在指定时间内尝试的次数是否已达到或超过限制 return $numiptry <= C::t('common_failedip')->get_ip_count($_G['clientip'], TIMESTAMP - $timeiptry);} /** * 记录一个失败的IP尝试。 */function failedip() { global $_G; // 插入当前IP到失败尝试表中 C::t('common_failedip')->insert_ip($_G['clientip']);} /** * 获取邀请码信息。 * * @return array 包含邀请码相关用户信息的数组,如果不存在有效邀请码则返回空数组。 */function getinvite() { global $_G; // 如果注册功能关闭,则直接返回空数组 if($_G['setting']['regstatus'] == 1) return array(); $result = array(); $cookies = empty($_G['cookie']['invite_auth']) ? array() : explode(',', $_G['cookie']['invite_auth']); $cookiecount = count($cookies); // 处理通过URL传入的邀请码 $_GET['invitecode'] = trim($_GET['invitecode']); if($cookiecount == 2 || $_GET['invitecode']) { $id = intval($cookies[0]); $code = trim($cookies[1]); if($_GET['invitecode']) { // 通过邀请码查询邀请信息 $invite = C::t('common_invite')->fetch_by_code($_GET['invitecode']); $code = trim($_GET['invitecode']); } else { // 通过ID查询邀请信息 $invite = C::t('common_invite')->fetch($id); } // 验证邀请信息的有效性 if(!empty($invite)) { if($invite['code'] == $code && empty($invite['fuid']) && (empty($invite['endtime']) || $_G['timestamp'] < $invite['endtime'])) { $result['uid'] = $invite['uid']; $result['id'] = $invite['id']; } } } elseif($cookiecount == 3) { // 处理通过cookie传入的邀请码 $uid = intval($cookies[0]); $code = trim($cookies[1]); $invite_code = helper_invite::generate_key($uid); if($code === $invite_code) { $member = getuserbyuid($uid); if($member) { $usergroup = C::t('common_usergroup')->fetch($member['groupid']); // 如果用户组不允许邀请或邀请需要付费,则返回空数组 if(!$usergroup['allowinvite'] || $usergroup['inviteprice'] > 0) return array(); } else { return array(); } $result['uid'] = $uid; } } // 如果获取到有效的邀请信息,填充邀请者用户名 if($result['uid']) { $member = getuserbyuid($result['uid']); $result['username'] = $member['username']; } else { // 如果没有有效的邀请信息,清除邀请cookie dsetcookie('invite_auth', ''); } return $result;}/** * 替换字符串中的站点变量 * * @param string $string 需要替换的字符串 * @param array $replaces 用户自定义的替换数组,默认为空数组 * @return string 替换后的字符串 */function replacesitevar($string, $replaces = array()) { global $_G; // 定义站点变量 $sitevars = array( '{sitename}' => $_G['setting']['sitename'], '{bbname}' => $_G['setting']['bbname'], '{time}' => dgmdate(TIMESTAMP, 'Y-n-j H:i'), '{adminemail}' => $_G['setting']['adminemail'], '{username}' => $_G['member']['username'], '{myname}' => $_G['member']['username'] ); // 合并用户自定义替换数组和站点变量 $replaces = array_merge($sitevars, $replaces); // 替换字符串并返回 return str_replace(array_keys($replaces), array_values($replaces), $string);} /** * 清除用户cookie */function clearcookies() { global $_G; // 遍历cookie,除去特定的键值,其余全部清除 foreach($_G['cookie'] as $k => $v) { if($k != 'widthauto') { dsetcookie($k); } } // 重置用户登录状态 $_G['uid'] = $_G['adminid'] = 0; $_G['username'] = $_G['member']['password'] = '';} /** * 处理犯罪记录相关操作 * * @param string $fun 要执行的操作 * @return mixed 操作结果,失败返回false */function crime($fun) { if(!$fun) { return false; } include_once libfile('class/member'); $crimerecord = & crime_action_ctl::instance(); $arg_list = func_get_args(); // 根据传入的函数名执行不同的操作 if($fun == 'recordaction') { list(, $uid, $action, $reason) = $arg_list; return $crimerecord->$fun($uid, $action, $reason); } elseif($fun == 'getactionlist') { list(, $uid) = $arg_list; return $crimerecord->$fun($uid); } elseif($fun == 'getcount') { list(, $uid, $action) = $arg_list; return $crimerecord->$fun($uid, $action); } elseif($fun == 'search') { list(, $action, $username, $operator, $starttime, $endtime, $reason, $start, $limit) = $arg_list; return $crimerecord->$fun($action, $username, $operator, $starttime, $endtime, $reason, $start, $limit); } elseif($fun == 'actions') { return crime_action_ctl::$actions; } return false;} /** * 检查并更新关注的动态 */function checkfollowfeed() { global $_G; if($_G['uid']) { $lastcheckfeed = 0; if(!empty($_G['cookie']['lastcheckfeed'])) { $time = explode('|', $_G['cookie']['lastcheckfeed']); if($time[0] == $_G['uid']) { $lastcheckfeed = $time[1]; } } if(!$lastcheckfeed) { $lastcheckfeed = getuserprofile('lastactivity'); } // 设置最后一次检查动态的时间 dsetcookie('lastcheckfeed', $_G['uid'].'|'.TIMESTAMP, 31536000); // 获取关注的用户 $followuser = C::t('home_follow')->fetch_all_following_by_uid($_G['uid']); $uids = array_keys($followuser); if(!empty($uids)) { // 检查是否有新的动态 $count = C::t('home_follow_feed')->count_by_uid_dateline($uids, $lastcheckfeed); if($count) { // 有新动态,添加通知 notification_add($_G['uid'], 'follow', 'member_follow', array('count' => $count, 'from_id'=>$_G['uid'], 'from_idtype' => 'follow'), 1); } } } // 更新检查动态的cookie dsetcookie('checkfollow', 1, 30);} /** * 验证邮箱格式及合法性 * * @param string $email 需要验证的邮箱地址 */function checkemail($email) { global $_G; $email = strtolower(trim($email)); if(strlen($email) > 255) { // 邮箱地址过长 showmessage('profile_email_illegal', '', array(), array('handle' => false)); } if($_G['setting']['regmaildomain']) { // 检查邮箱域名是否合法 $maildomainexp = '/('.str_replace("\r\n", '|', preg_quote(trim($_G['setting']['maildomainlist']), '/')).')$/i'; if($_G['setting']['regmaildomain'] == 1 && !preg_match($maildomainexp, $email)) { showmessage('profile_email_domain_illegal', '', array(), array('handle' => false)); } elseif($_G['setting']['regmaildomain'] == 2 && preg_match($maildomainexp, $email)) { showmessage('profile_email_domain_illegal', '', array(), array('handle' => false)); } } // 调用ucenter接口验证邮箱 loaducenter(); $ucresult = uc_user_checkemail($email); // 处理ucenter返回的结果 if($ucresult == -4) { showmessage('profile_email_illegal', '', array(), array('handle' => false)); } elseif($ucresult == -5) { showmessage('profile_email_domain_illegal', '', array(), array('handle' => false)); } elseif($ucresult == -6) { showmessage('profile_email_duplicate', '', array(), array('handle' => false)); }} /** * 生成获取密码的签名链接 * * @param int $uid 用户ID * @param string $idstring 用户注册ID字符串 * @return string 签名链接 */function make_getpws_sign($uid, $idstring) { global $_G; $link = "member.php?mod=getpasswd&uid={$uid}&id={$idstring}"; return dsign($link);} ?>