牛骨文教育服务平台(让学习变的简单)
博文笔记

Discuz中session机制流程图以及心得

创建时间:2015-07-15 投稿人: 浏览次数:2079

下面这个流程图是我在网上找到的,顺着流程图,可以更深入的学习discuz的session机制



当初始化application时,对session进行初始化。代码主要实现以下功能:

1.判断session状态是否为开启,开启则继续

2.将cookie下的sid赋值给session中 sid,保持session和cookie中的sid保持相同。当session中的sid和cookie的sid不一致或者sid不存在,则重新创建sid,并更新cookie。

3.获取上次用户活动状态,如果未登录,则将用户组设置为游客并关联ip。如果登录,记录用户上次登录时间和ip。

代码如下:source/class/discuz/discuz_application.php

private function _init_session() {

		$sessionclose = !empty($this->var["setting"]["sessionclose"]);
		$this->session = $sessionclose ? new discuz_session_close() : new discuz_session();

		if($this->init_session)	{
			$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;

			if(!empty($this->var["sid"]) && $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;
				if(!defined("IN_MOBILE_API")) {
					sysmessage("user_banned");
				} else {
					mobile_core::result(array("error" => "user_banned"));
				}
			}

			if($this->var["uid"] && !$sessionclose && ($this->session->isnew || ($this->session->get("lastactivity") + 600) < TIMESTAMP)) {
				$this->session->set("lastactivity", TIMESTAMP);
				if($this->session->isnew) {
					if($this->var["member"]["lastip"] && $this->var["member"]["lastvisit"]) {
						dsetcookie("lip", $this->var["member"]["lastip"].",".$this->var["member"]["lastvisit"]);
					}
					C::t("common_member_status")->update($this->var["uid"], array("lastip" => $this->var["clientip"], "port" => $this->var["remoteport"], "lastvisit" => TIMESTAMP));
				}
			}

		}
	}

创建sid代码:source/class/discuz/discuz_session;

public function create($ip, $uid) {
		$this->isnew = true;
		$this->var = $this->newguest;
		$this->set("sid", random(6));
		$this->set("uid", $uid);
		$this->set("ip", $ip);
		$uid && $this->set("invisible", getuserprofile("invisible"));
		$this->set("lastactivity", time());
		$this->sid = $this->var["sid"];
		return $this->var;
	}

在论坛开发或者模版制作中,比较关心的session是用户在线时长和用户登录状态记录。

关于在线时长的知识,请参考:为什么Discuz! X会员在线时间不更新,解析dz在线时间机制


看了discuz的session机制,有一点拙见:

为什么我们要用数据库来记录session状态呢?

我觉得一来是数据库可以实现持久化的效果。二来,对于一个大中型的网站,例如社交网站,或电商网站,需要一个稳定的状态共享的确保。就像一个人的旅行,他将所有的现金集中放到银行,每到达一个目的地的时候,如果需要就可以很方便的仅仅使用银行卡就可以解决金钱问题,也可以在旅途中将额外的金钱随时存入银行。这样的目的,使得他能在不同时刻不同地点来进行金钱的存取,即使说有一天他身上取出的现金丢了,也可以使用银行卡来保证剩下的旅途的金钱保障。大的网站会将session独立出来,放置在专用的服务器上,当分布系统有宕机出现,备用的容错系统就可以很快的恢复到之前的状态。当然这一个过程需要很多方面的支持才行,这里只是一个很小的session部分。

而就discuz的session中,session记录表中只记录一些初始的状态,更多的都是使用cookie来记录。这和discuz的服务对象是分不开的,假如当有一天,discuz成了shopnc,session能实现的就远远不止记录当前状态这么少了。


声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。