Php代码
Discuz! X 中 SESSION 机制讲解
在Discuz! X中一如继往的,SESSION 并没有使用 PHP 自带的 SESSION 机制,而是系统的一套自带的机制。
在数据库中可以看到有两个 SESSION 表:
一个是pre_common_adminsession,是管理员登录后台的 SESSION 表;
另一个是 pre_common_session 表,是所有用户在前台浏览页面时的 SESSION 表。
这两个表都是内存表(内存表的读写速度远高于 MYISAM 表及文本文件)。
在 Discuz! X 中 SESSION 与 COOKIE 是分不开的,因为 SESSION 就是从客户端读取的 COOKIE ,
然后由浏览页面时触发相关的函数执行,再写入数据库 SESSION 表。
我以登录流程为例来讲解程序具体是如何执行的。
在前台首页,点击登录后,弹出一个登录窗口,填写好数据后,提交。form表单提交的 URL 是:
1 http://ux.com/member.php?mod=logging&action=login&loginsubmit=yes&floatlogin=yes&inajax=1
数据提交到了 member.php 文件中,在程序中可看到下面的代码:
01 $mod = !in_array($discuz->var['mod'], $modarray) ? 'logging' : $discuz->var['mod']; //mod的值即是接下来加载的php页面
02 define('CURMODULE', $mod);
03 $modcachelist = array('register' => array('modreasons', 'stamptypeid', 'fields_required', 'fields_optional', 'ipctrl'));
04 $cachelist = array();
05 if(isset($modcachelist[CURMODULE])) {
06 $cachelist = $modcachelist[CURMODULE];
07 }
08 $discuz->cachelist = $cachelist;
09 $discuz->init();
10 runhooks();
11 require DISCUZ_ROOT.'./source/module/member/member_'.$mod.'.php'; //完成程序的包含操作
打开source/module/member/member_logging.php文件,是一个类,在类的前面可看到下面三句代码:
$ctl_obj = new logging_ctl();
$method = 'on_'.$_G['gp_action']; // $_G['gp_action'] 等于action的值即 login
$ctl_obj->$method(); //$ctl_obj->on_login();
在类中可找到login方法,在方法中,大约 56 行有下面一个判断语句:
if(!submitcheck('loginsubmit', 1, $seccodecheck)) {
判断语句是当游客浏览时,submitcheck 函数的返回值是假,取反,为真。
当用户登录时,程序走的是else部分,在里面可看到下面五句代码:
} else {
$_G['uid'] = $_G['member']['uid'] = 0;
$_G['username'] = $_G['member']['username'] = $_G['member']['password'] = ''; //变量赋值
$result = userlogin($_G['gp_username'], $_G['gp_password'], $_G['gp_questionid'], $_G['gp_answer'], $_G['setting']['autoidselect'] ? 'auto' : $_G['gp_loginfield']); //从数据库查询用户数据,并返回相应的信息
if($result['status'] > 0) { //状态值大于 0 ,说明有此用户,可以登录
setloginstatus($result['member'], $_G['gp_cookietime'] ? 2592000 : 0); //设置登录状态,即是写 COOKIE 操作,COOKIE 中的数据即是 SESSION 中相应的数据,但此函数并不负责写 SESSION 的操作
我们来看一下 source/function/function_login.php中的 setloginstatus 函数,是普通的写 COOKIE 操作,不再具体讲解:
function setloginstatus($member, $cookietime) {
global $_G;
$_G['uid'] = $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;
$_G['core']->session->isnew = 1;
dsetcookie('auth', authcode("{$member['password']}\t{$member['uid']}", 'ENCODE'), $cookietime, 1, true); //authcode加密
dsetcookie('loginuser');
dsetcookie('activationauth');
dsetcookie('pmnum');
}
到这里可以说是登录流程大部分已经走完,但是 COOKIE 不清除时,会一直存在于客户端,如果超时,程序中会在判断弃用此 COOKIE,并重新写入。
下面我们来看一下 DZX 中 SESSION 操作的类,在 source/class/calss_core.php 文件中:
程序中每次请求都会加载 SESSION ,这是由核心类 discuz_core 中的 _init_session 方法来执行的,此方法被置于 类的 init方法中,说明每次加载类,会自动将 SESSION 写入。
function _init_session() {
$this->session = new discuz_session(); //创建 SESSION 类
if($this->init_session) {
//从 COOKIE 中读取数据
$this->session->init($this->var['cookie']['sid'], $this->var['clientip'], $this->var['uid']);
$this->var['sid'] = $this->session->sid;
$this->var['session'] = $this->session->var;
//判断 SID 是否相等,不等,说明是多个用户在同一主机上登录网站,需要重新写 COOKIE
if($this->var['sid'] != $this->var['cookie']['sid']) {
dsetcookie('sid', $this->var['sid'], 86400);
}
if($this->session->isnew) {
if(ipbanned($this->var['clientip'])) {
$this->session->set('groupid', 6);
}
}
if($this->session->get('groupid') == 6) {
$this->var['member']['groupid'] = 6;
sysmessage('user_banned');
}
//UID 不为空,且需要更新 SESSION 或是 SESSION 超时,更改用户状态,需要用户重新登录
if($this->var['uid'] && ($this->session->isnew || ($this->session->get('lastactivity') + 600)
$this->session->set('lastactivity', TIMESTAMP);
$update = array('lastip' => $this->var['clientip'], 'lastactivity' => TIMESTAMP);
if($this->session->isnew) {
$update['lastvisit'] = TIMESTAMP;
}
DB::update('common_member_status', $update, "uid='".$this->var['uid']."'");
}
}
}
操作 SESSION 的类是 discuz_session ,我们看这个类里面的两个方法:
//此函数负责产生新的 SESSION,但并不负责写入数据库
function create($ip, $uid) {
//创建SESSION,执行插入数据,由随机函数产生一个六位随机数即是session的唯一值时间为当前时间,sid为cookie中的sid
$this->isnew = true;
$this->var = $this->newguest;
$this->set('sid', random(6));
$this->set('uid', $uid);
$this->set('ip', $ip);
$this->set('lastactivity', time());
$this->sid = $this->var['sid'];
return $this->var;
}
//此函数负责更新 SESSION
function update() {
if($this->sid !== null) {
$data = daddslashes($this->var);
if($this->isnew) {
$this->delete();
DB::insert('common_session', $data, false, false, true);
} else {
DB::update('common_session', $data, "sid='$data[sid]'");
}
dsetcookie('sid', $this->sid, 86400);
}
}
至此我们知道了 SESSION 插入数据库的具体函数,与 COOKIE 的联系,但还不清楚是如何触发此操作的。
打开 source/function/function_core.php 文件,找到函数,updatesession ,此函数负责更新 SESSION :
function updatesession($force = false) {
global $_G;
static $updated = false;
if(!$updated) {
$discuz = & discuz_core::instance();
foreach($discuz->session->var as $k => $v) {
if(isset($_G['member'][$k]) && $k != 'lastactivity') {
$discuz->session->set($k, $_G['member'][$k]);
}
}
foreach($_G['action'] as $k => $v) {
$discuz->session->set($k, $v);
}
$discuz->session->update();
$updated = true;
}
return $updated;
}
我们在程序源码中搜索此函数,可以看到在很多的模板中都有下面一句代码:
{eval updatesession();}
浏览页面时将触发此函数,并将 SESSION 写入数据库。
整理一下思绪:
第一步:用户登录,程序将 COOKIE 写入客户端,这些 COOKIE 即是 SESSION 的部分数据,如SID、IP、TIME,不包含用户名、密码等关键信息。
第二步,登录成功后,程序会自动刷新页面,向服务器再次发送请求,服务器加载 discuz_core 核心类,并从 COOKIE 中读取到 SESSION 的相关信息,但还没有写入数据库。
第三步,核心类加载完成,程序继续执行,最后加载模板,触发 updatesession 函数,SESSION 被写入数据库。
作者“pz9042”

로드 밸런싱은 세션 관리에 영향을 미치지 만 세션 복제, 세션 끈적임 및 중앙 집중식 세션 스토리지로 해결할 수 있습니다. 1. 세션 복제 복사 서버 간의 세션 데이터. 2. 세션 끈은 사용자 요청을 동일한 서버로 안내합니다. 3. 중앙 집중식 세션 스토리지는 Redis와 같은 독립 서버를 사용하여 세션 데이터를 저장하여 데이터 공유를 보장합니다.

SessionLockingIsateChniqueSureDureauser의 SessionLockingSsessionRemainSexclusivetoOneuseratatime.itiscrucialforpreptingdatacorruptionandsecurityBreachesInmulti-userApplications.sessionLockingSogingSompletEdusingserVerver-sidelockingMegynisms, unrasprantlockinj

PHP 세션의 대안에는 쿠키, 토큰 기반 인증, 데이터베이스 기반 세션 및 Redis/Memcached가 포함됩니다. 1. Cookies는 클라이언트에 데이터를 저장하여 세션을 관리합니다. 이는 단순하지만 보안이 적습니다. 2. Token 기반 인증은 토큰을 사용하여 사용자를 확인합니다. 이는 매우 안전하지만 추가 논리가 필요합니다. 3. Database 기반 세션은 데이터베이스에 데이터를 저장하여 확장 성이 좋지만 성능에 영향을 줄 수 있습니다. 4. Redis/Memcached는 분산 캐시를 사용하여 성능 및 확장 성을 향상하지만 추가 일치가 필요합니다.

SessionHijacking은 사용자의 SessionID를 얻음으로써 사용자를 가장하는 공격자를 말합니다. 예방 방법은 다음과 같습니다. 1) HTTPS를 사용한 의사 소통 암호화; 2) SessionID의 출처를 확인; 3) 보안 세션 생성 알고리즘 사용; 4) 정기적으로 SessionID를 업데이트합니다.

이 기사는 PHP에 대해 설명하고, 전체 형식, 웹 개발의 주요 용도, Python 및 Java와의 비교 및 초보자를위한 학습 용이성을 자세히 설명합니다.

PHP는 유효성 검사, 소독 및 보안 데이터베이스 상호 작용을 통해 보안을 보장하면서 $ \ _ post 및 $ \ _를 사용하여 데이터 양식 데이터를 처리합니다.

이 기사는 PHP와 ASP.NET을 비교하여 대규모 웹 응용 프로그램, 성능 차이 및 보안 기능에 대한 적합성에 중점을 둡니다. 둘 다 대규모 프로젝트에서는 실용적이지만 PHP는 오픈 소스 및 플랫폼 독립적이며 ASP.NET,

PHP의 사례 감도는 다양합니다. 함수는 무감각하고 변수와 클래스는 민감합니다. 모범 사례에는 일관된 이름 지정 및 비교를위한 사례 감수 기능 사용이 포함됩니다.


핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

Video Face Swap
완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

인기 기사

뜨거운 도구

Dreamweaver Mac版
시각적 웹 개발 도구

mPDF
mPDF는 UTF-8로 인코딩된 HTML에서 PDF 파일을 생성할 수 있는 PHP 라이브러리입니다. 원저자인 Ian Back은 자신의 웹 사이트에서 "즉시" PDF 파일을 출력하고 다양한 언어를 처리하기 위해 mPDF를 작성했습니다. HTML2FPDF와 같은 원본 스크립트보다 유니코드 글꼴을 사용할 때 속도가 느리고 더 큰 파일을 생성하지만 CSS 스타일 등을 지원하고 많은 개선 사항이 있습니다. RTL(아랍어, 히브리어), CJK(중국어, 일본어, 한국어)를 포함한 거의 모든 언어를 지원합니다. 중첩된 블록 수준 요소(예: P, DIV)를 지원합니다.

SublimeText3 Linux 새 버전
SublimeText3 Linux 최신 버전

Atom Editor Mac 버전 다운로드
가장 인기 있는 오픈 소스 편집기

PhpStorm 맥 버전
최신(2018.2.1) 전문 PHP 통합 개발 도구
