xsphp_会话控制

<?php

	/*
		cookie基本操作
		cookie是一种由服务器发送给客户端的片段信息,存储在客户端浏览器的内存或者硬盘上。
		在客户对该服务的请求中发回它。
		cookie文件会放在 C:\Documents and Settings\用户名\Cookies

		例如此程序生成的cookie文件名   用户名@localhost[1].txt
	*/


	//设置cookie
	$time = time() +  60 * 60;  //设置cookie生存时间,必须设定时间.(保存1小时)
	//$time = time() + 60 * 60 * 24 * 7   保存一周
	setCookie("user",'yuanchao',$time);

	//获取cookie
	print_r($_COOKIE);

	echo $_COOKIE['user'];
<?php

	/*
		数组形态的cookie
	*/

	$time = time() + 60 * 60;
	/*
		在setCookie()函数的第一个参数中,通过在cookie标识中指定数组下标的形式设置。
	*/
	setCookie('user[name]','yuanchao',$time);
	setCookie('user[age]','30',$time);
	setCookie('user[sex]','男',$time);

	foreach($_COOKIE["user"] as $key=>$value) {
		echo $key .'--' . $value .'<br/>';
	}
<?php

	/*
		删除cookie
		如果删除在客户端的cookie,可以使用两种方法。
		
		第一种:省略setcookie()函数的所有参数列,仅仅只有第一个参数的cookie名称即可。
		
		第二种:利用setcookie()函数把cookie设定为已过期状态。即减去-1
	*/

	//第一种方式
	setCookie('user');

	//第二种方式

	setCookie('user[name]','',time()-1);

基于cookie的用户登陆模块

--创建用户表,allow权限位,1代表有权限,0代表无权限
create table user (
	id	int primary key auto_increment,
	name varchar(20) not null,
	pwd varchar(50) not null,
	allow_1 int(1) not null,
	allow_2 int(1) not null,
	allow_3 int(1) not null
);
--建立管理员和yc普通用户
insert into user values(null,'admin',md5('admin'),1,1,1);
insert into user values(null,'yc',md5('yc'),0,0,1);

mysql> select * from user;
+----+-------+----------------------------------+---------+---------+---------+
| id | name  | pwd                              | allow_1 | allow_2 | allow_3 |
+----+-------+----------------------------------+---------+---------+---------+
|  1 | admin | 21232f297a57a5a743894a0e4a801fc3 |       1 |       1 |       1 |
|  2 | yc    | a2bf364d91c65964491d6ef7c0a36c46 |       0 |       0 |       1 |
+----+-------+----------------------------------+---------+---------+---------+
2 rows in set (0.00 sec)


conn.inc.php

<?php
	
	/*
		连接数据库
	*/

	$mysqli = new mysqli('localhost','root','root','xsphp');
	if(mysqli_connect_errno()) {
		printf('数据库连接失败,失败原因:%s',mysqli_connect_error());
		exit;
	}

comm.inc.php

<?php

	/*
		检查cookie,判断是否登陆
	*/
	if(!isset($_COOKIE["islogin"]) && $_COOKIE["islogin"] != true) {
		var_dump($_COOKIE["islogin"]);
		header('location:login.php');
	}

login.php

<html>
	<head>
		<title>基于cookie的用户登陆模块</title>
		<?php
			if(isset($_POST['sub'])) {
				include('conn.inc.php');
				$name = $_POST['name'];
				$pwd = $_POST['pwd'];
				$sql = 'select id from user where name ="'.$name.'" and pwd = "'.md5($pwd).'" ';
			//echo $sql;
				$result = $mysqli->query($sql);
				if($result->num_rows > 0) {
					$row = $result->fetch_assoc();
					//登陆成功,设置cookie
					$time = time() + 60 * 60;  //失效时间1小时
					setCookie('name',$name,$time);
					setCookie('islogin',true,$time);
					setCookie('id',$row['id'],$time);
					$result->close();
					$mysqli->close();
					header('location:index.php');
				}
				$mysqli->close();
				echo '登陆失败!';
			}
		?>
	</head>
	<body>
	<form action="login.php" method="post" name="myform">
		<table border="1" align="center">
			<tr>
				<td>
				用户名:
				</td>
				<td>
					<input type="text" name="name" />
				</td>
			</tr>
			<tr>
				<td>
				密码:
				</td>
				<td>
					<input type="password" name="pwd" />
				</td>
			</tr>
			<tr>
				<td colspan="2">
					<input type="submit" name="sub" value="登陆"/>
				</td>
			</tr>
		</table>
	</form>
	</body>
</html>

index.php

<?php

	/*
		主界面 
	*/

	include('comm.inc.php');
	include('conn.inc.php');
	
	$name = $_COOKIE['name'];
	$id = $_COOKIE['id'];
	echo "欢迎{$name}回来 <br/>";
	echo "<a href='logout.php'>退出登陆</a> <br/>";
	$sql = "select * from user where id = " . $id;
	$result = $mysqli->query($sql);
	$row = $result->fetch_assoc();
	if($row['allow_1'] == 1) {
		echo '您拥有allow_1权限 <br/>';
	}
	if($row['allow_2'] == 1) {
		echo '您拥有allow_2权限 <br/>';
	}
	if($row['allow_3'] == 1) {
		echo '您拥有allow_3权限 <br/>';
	}
	$result->close();
	$mysqli->close();

logout.php

<?php

	include('comm.inc.php');

	//删除cookie
	setCookie('name');
	setCookie('id');
	setCookie('islogin');

	header('location:login.php');



Session

<?php

	/*
		Session

		session的设置不同于cookie,必须先启动。
	*/
	
	//开启session,此函数之前不能有任何输出
	session_start(); 

	$_SESSION['username'] = 'hello world';

	echo session_id().'<br/>'; //输出sessionid

	echo $_SESSION['username'] .'<br/>';

	//输出pip.ini文件里session.name
	echo session_name().'<br/>';

<?php

	/*
		session销毁步骤
	*/

	//第一步,开启session
	session_start();
	//第二步,删除所有session变量
	$_Session = array();
	//第三步,如果是基于cookie的session,使用setcookie()删除包含session id的cookie
	if(isset($_COOKIE[session_name()])) {
		setCookie(session_name(),'',time()-3600,'/');
	}
	//第四步,最后彻底销毁session
	session_destroy();


	/*
		$_Session = array(); 清空$_SESSION数组的同时,也将这个用户在服务器端对应的session文件内容清空。

		而使用session_destroy();则是将这个用户在服务器端对应的session文件删除
	*/

基于session登陆模块

comm.inc.php

<?php

	/*
		检查session,判断是否登陆
	*/
	session_start();
	if(!isset($_SESSION["islogin"]) && $_SESSION["islogin"] != true) {
		header('location:login.php');
	}

login.php

<html>
	<head>
		<title>基于session的用户登陆模块</title>
		<?php
		//开启session
		session_start();
			if(isset($_POST['sub'])) {
				include('conn.inc.php');
				$name = $_POST['name'];
				$pwd = $_POST['pwd'];
				$sql = 'select id from user where name ="'.$name.'" and pwd = "'.md5($pwd).'" ';
			//echo $sql;
				$result = $mysqli->query($sql);
				if($result->num_rows > 0) {
					$row = $result->fetch_assoc();
					//登陆成功,设置session
					$_SESSION['name'] = $name;
					$_SESSION['id'] = $row['id'];
					$_SESSION['islogin'] = true;
					$result->close();
					$mysqli->close();
					header('location:index.php');
				}
				$mysqli->close();
				echo '登陆失败!';
			}
		?>
	</head>
	<body>
	<form action="login.php" method="post" name="myform">
		<table border="1" align="center">
			<tr>
				<td>
				用户名:
				</td>
				<td>
					<input type="text" name="name" />
				</td>
			</tr>
			<tr>
				<td>
				密码:
				</td>
				<td>
					<input type="password" name="pwd" />
				</td>
			</tr>
			<tr>
				<td colspan="2">
					<input type="submit" name="sub" value="登陆"/>
				</td>
			</tr>
		</table>
	</form>
	</body>
</html>

index.php

<?php

	/*
		主界面 
	*/

	include('comm.inc.php');
	include('conn.inc.php');
	$name = $_SESSION['name'];
	$id = $_SESSION['id'];
	echo "欢迎{$name}回来 <br/>";
	echo "<a href='logout.php'>退出登陆</a> <br/>";
	$sql = "select * from user where id = " . $id;
	$result = $mysqli->query($sql);
	$row = $result->fetch_assoc();
	if($row['allow_1'] == 1) {
		echo '您拥有allow_1权限 <br/>';
	}
	if($row['allow_2'] == 1) {
		echo '您拥有allow_2权限 <br/>';
	}
	if($row['allow_3'] == 1) {
		echo '您拥有allow_3权限 <br/>';
	}
	$result->close();
	$mysqli->close();

使用URL传递session id的登陆模块

方法:

       第一个方法:手动的在每个超级链接的URL中都添加一个session.
            页面都要判断一下是否有传过来的session id, 有则设置一下。


    第二个方法:使用pip.ini里的session.name = PHPSESSID
                 <a href="链接?PHPSESSID=".session_id()>xxxxxx</a>
             就不需要判断了。session自动找PHPSESSID

    第三个方法:
            使用常量SID:
            该常量在会话启动时被定义,如果客户端没有发送是的会话cookie,则sid的格式为
            session_name = session_id,否则就是一个空字符串。
        <a href="链接?".SID>xxxxxx</a>
            也不需要判断

    
       第四个方法:
        修改php.ini里的session.use_trans_sid = 1.使用明码在URL显示sid.(不建议使用)

第一种方法的代码:

login.php

<html>
	<head>
		<title>基于session的用户登陆模块</title>
		<?php
		//开启session
		if(isset($_GET['sid'])) {
			session_id($_GET['sid']);
		}
		session_start();
		
		
		echo session_id().'<br/>';
			if(isset($_POST['sub'])) {
				include('conn.inc.php');
				$name = $_POST['name'];
				$pwd = $_POST['pwd'];
				$sql = 'select id from user where name ="'.$name.'" and pwd = "'.md5($pwd).'" ';
			//echo $sql;
				$result = $mysqli->query($sql);
				if($result->num_rows > 0) {
					$row = $result->fetch_assoc();
					//登陆成功,设置session
					$_SESSION['name'] = $name;
					$_SESSION['id'] = $row['id'];
					$_SESSION['islogin'] = true;
					$result->close();
					$mysqli->close();
					//header('location:index.php?sid='.session_id());
					
					echo '<script>';
					echo 'alert("aaaa");';
					echo "location='index.php?sid=".session_id()."'";
					echo '</script>';

					echo '------------------------';
					
				}else {
					$mysqli->close();
					echo '登陆失败!';
				}
			}
		?>
	</head>
	<body>
	<form action="login.php?sid=<?php echo session_id();?>" method="post" name="myform">
		<table border="1" align="center">
			<tr>
				<td>
				用户名:
				</td>
				<td>
					<input type="text" name="name" />
				</td>
			</tr>
			<tr>
				<td>
				密码:
				</td>
				<td>
					<input type="password" name="pwd" />
				</td>
			</tr>
			<tr>
				<td colspan="2">
					<input type="submit" name="sub" value="登陆"/>
				</td>
			</tr>
		</table>
	</form>
	</body>
</html>

commit.inc.php

<?php

	/*
		检查session,判断是否登陆
	*/
	
	//判断URL是否有session id.如果有则设置。必须放在开启sesion之前。否则session会有新的id
	if(isset($_GET['sid'])) {
			session_id($_GET['sid']);
			echo session_id();
	}
	session_start();
	if(!isset($_SESSION["islogin"]) && $_SESSION["islogin"] != true) {
	echo '))))))))))))))))))';
		//header('location:login.php');
	}
	

php.ini中与会话session有关的几个选项

存储和检索与胡话关联的数据的处理器名字,可以使用(files,user,sqlite,memcahce)中的一个值
默认为文件files,如果想要使用自定义的处理器,可以用user
session.save_handler = user

对于files处理器,此值是创建会话数据文件的路径。
session.save_path = "/tmp"

是否使用cookie在客户端保存会话id,1表示允许
session.use_cookies = 1

会话的名称
session.name = PHPSESSID

是否使用明码在URL上显示SID(会话ID)。默认禁止
session_use_trans_sid

cookie中的session id在客户机上保存的有效期(秒),0表示延续到浏览器关闭。
session.cookie_lifetime = 0  

传递会话id的cookie作用路径

session.cookie_path = /


Session的自动回收机制

通过在页面中提供的一个退出按钮,单击销毁本次会话。但用户如果没有单击退出按钮,而是直接关闭浏览器。
或断网等情况,在服务器保存的session文件是不会被删除的。虽然关闭浏览器,下次需要分配一个新的session id重新登录。
通过在php.ini中设置session.gc_maxlifetime选项来指定一个时间(单位:秒),例如1400(24分钟)
通过在php.ini文件中修改session.gc_probability和session.gc_divisor两个选项,设置启动垃圾回收程序的概率。
会根据session.gc_probability/session.gc_divisor公式计算概率,例如session.gc_probability=1,session.gc_divisor=100

这样的概率就是1/100.即session_start()函数被调用100次才会有一次可能启动垃圾回收程序。建议值为1/(1000~5000)


自定义session处理方式。

1、存储到文件中。session默认也是存储到文件中

session.php

<?php
	
	//在运行session_start(); //启动
	function open($save_path, $session_name){
		global $sess_save_path;

		$sess_save_path=$save_path;

		return true;
	}
	//session_write_close()  session_destroy() 
	function close(){
		return true;
	}
	//session_start(), $_SESSION, 读取session数据到$_SESSION中
	function read($id){
		global $sess_save_path;
		$sess_file=$sess_save_path."/glf_".$id;

		return (string)@file_get_contents($sess_file);
		
	}
	//结束时和session_write_close()强制提交SESSION数据 $_SESSION[]="aaa";
	function write($id, $sess_data){
		global $sess_save_path;
		$sess_file=$sess_save_path."/glf_".$id;

		if($fp=@fopen($sess_file, "w")){
			$return=fwrite($fp, $sess_data);
			fclose($fp);
			return $return;
		}else{
			return false;
		}

	}
	//session_destroy()
	function destroy($id){
		global $sess_save_path;
		$sess_file=$sess_save_path."/glf_".$id;

		return @unlink($sess_file);
	}

	//ession.gc_probability和session.gc_divisor值决定的,open(), read() session_start也会执行gc
	function gc($maxlifetime){
		global $sess_save_path;
		
		/*
			glob() 函数依照 libc glob() 函数使用的规则寻找所有与 pattern 匹配的文件路径 
			返回一个包含有匹配文件/目录的数组。如果出错返回 FALSE。 

		*/
		foreach(glob($sess_save_path."/glf_*") as $filename){
			//文件的修改时间+文件生存时间 小于 当前时间,是过期文件
			if(filemtime($filename)+$maxlifetime < time() ){
				@unlink($filename);
				echo $filename;
			}
		}

		return true;
	}

	session_set_save_handler("open", "close", "read", "write", "destroy","gc");

	session_start();

one.php

<?php

	include('session.php');
	//session_start();
	$_SESSION['username'] = 'yc';
	$_SESSION['pwd'] = 'admin';

	echo session_name() . '=' .session_id();

two.php

<?php

	include('session.php');

	echo $_SESSION['username']."<br/>";
	echo $_SESSION['pwd']."<br/>";

	echo session_name().'='.session_id();

three.php

<?php

	include('session.php');
	$_SESSION = array();
	if(isset($_COOKIE[session_name()])) {
		setCookie(session_name(),'',time()-100,'/');
	}
	session_destroy();

	echo 'session已销毁';

	echo session_name().'='.session_id();

生存的sesson文件

yctupqf4kc44d147sonkqhsfcil1

username|s:2:"yc";pwd|s:5:"admin";

2、使用数据库处理Session信息

--创建保存session信息表

create	table session(
	sid	char(32) not null primary key,   #session id
	client_ip char(15) not null,   #客户端IP
	update_time int not null,    #session的更新时间
	data text                    #session数据
);

mysql> desc session;
+-------------+----------+------+-----+---------+-------+
| Field       | Type     | Null | Key | Default | Extra |
+-------------+----------+------+-----+---------+-------+
| sid         | char(32) | NO   | PRI | NULL    |       |
| client_ip   | char(15) | NO   |     | NULL    |       |
| update_time | int(11)  | NO   |     | NULL    |       |
| data        | text     | YES  |     | NULL    |       |
+-------------+----------+------+-----+---------+-------+
4 rows in set (0.00 sec)

session.php

<?php

	/*
		利用数据库存储session
	*/

	class Session {
		private static $client_ip ; //客户端IP
		private static $lifetime;   //php.ini里的session的生存时间
		private static $time;    //当前时间
		private static $handle;    //数据库连接对象

		/*
			初始化对象
		*/
		private static function init($handle) {
			self::$handle = $handle;
			self::$client_ip = isset($_SERVER['REMOTE_ADDR'])?$_SERVER['REMOTE_ADDR']:'unknow';
			self::$lifetime = ini_get("session.gc_maxlifetime");
			self::$time =time();
		}

		public function start($pdo) {
			//回调函数调用类中方法,得用数组形式
			session_set_save_handler ( 
				array(__CLASS__,"open"),
				array(__CLASS__,"close"),
				array(__CLASS__,"read"),
				array(__CLASS__,"write"),
				array(__CLASS__,"destroy"),
				array(__CLASS__,"gc")
			 );
			self::init($pdo);
			//开启会话,启用数据库存储session
			session_start();
		}

		public static function open($path,$name) {
			return true;
		}

		public static function close() {
			return true;
		}
		/*
			读取数据库里session信息
		*/
		public static function read($id) {
			$sql = 'select client_ip,update_time,data from session where sid = ?';
			$stmt = self::$handle->prepare($sql);
			$stmt->bindParam(1,$id);
			$stmt->execute();
			$row = $stmt->fetch(PDO::FETCH_ASSOC);
			//如果客户端IP与数据库IP不一致,session过期
			if(self::$client_ip != $row['client_ip']) {
				self::destroy($id);
				return '';
			}
			//如果用户长时间没有操作,session已过期
			if($row['update_time'] + self::$lifetime < self::$time) {
				self::destroy($id);
				return '';
			}
			return $row['data'];
		}

		/*
			向数据库写入session信息
		*/
		public static function write($id,$data) {
			//首先判断数据库里是否有此session,如果有更新,没有插入
			$sql = 'select client_ip,update_time,data from session where sid = ?';
			$stmt =self::$handle->prepare($sql);
			$stmt->bindParam(1,$id);
			$stmt->execute();
			if($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
				//如果session数据没有改变,或者在30秒改变则更新
				if($row['data'] != $data || self::$time > $row['update_time'] + 30) {
					$sql = "update session set client_ip=?,update-time=?,data=? where sid = ?";
					$stmt = self::$handle->prepare($sql);
					$stmt->bindParam(1,self::$client_ip);
					$stmt->bindParam(2,self::$time);
					$stmt->bindParam(3,$data);
					$stmt->bindParam(4,$id);
					$stmt->execute();
				}
			}else {
				//插入新的session信息
				$sql = "insert into session values(?,?,?,?)";
				$stmt = self::$handle->prepare($sql);
				$stmt->execute(array($id,self::$client_ip,self::$time,$data));
			}
			return true;
		}

		/*
			销毁session
			删除数据库里session信息
		*/
		public static function destroy($id) {
			$sql = "delete from session where sid = ?";
			$stmt = self::$handle->prepare($sql);
			return $stmt->execute(array($id));
		}

		public static function gc($maxlifetime) {
			$sql = "delete from session where update_time < ?";
			$stmt = self::$handle->prepare($sql);
			//当前时间 - session生存时间
			$deletetime = self::time - self::lifetime;
			$stmt->bindParam(1,$deletetime);
			return $stmt->execute();
		}
	}

	try {
		$dsn = "mysql:dbname=xsphp;host=localhost";
		$user = 'root';
		$pwd = 'root';
		$opt = array(PDO::ATTR_PERSISTENT=>true,PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION);
		$pdo = new PDO($dsn,$user,$pwd,$opt);
	}catch(PDOException $e) {
		$e->getMessage();
	} 

	$sess = new Session();
	$sess->start($pdo);

运行one.php,two.php页面。在数据库里查询

mysql> select * from session;
+----------------------------+-----------+-------------+------------------------------------+
| sid                        | client_ip | update_time | data                               |
+----------------------------+-----------+-------------+------------------------------------+
| iclle0k85ga6ka8f2532a0gtn3 | 127.0.0.1 |  1523950782 | username|s:2:"yc";pwd|s:5:"admin"; |
+----------------------------+-----------+-------------+------------------------------------+
1 row in set (0.00 sec)

3、使用memcache处理session信息

memcache.class.php

<?php

	/*
		用数据库来同步Session会加大数据库的负担。
		用文件存储,读取慢。
		用memcache来处理session则是非常合适。
		memcache的缓存机制和session非常相似。另外,memcache可以做分布式。
		能够把web服务器中的内存组合起来,成为一个内存池。
	*/

	class MemSession {
		private static $lifetime;  //session生存时间
		private static $handle;    //memcache对象
		const NS = 'memcache_';   //声明一个session名的前缀,防止冲突

		/*
			对象初始化
		*/
		public static function init($handle) {
			self::$lifetime = ini_get("session.gc_maxlifetime");
			self::$handle = $handle;
		}

		public static function start($mem) {
			self::init($mem);
			session_set_save_handler ( 
				array(__CLASS__,"open") ,
				array(__CLASS__,"close") ,
				array(__CLASS__,"read") ,
				array(__CLASS__,"write") ,
				array(__CLASS__,"destroy") ,
				array(__CLASS__,"gc") 
			);
			//开启会话,启用memcache存储session
			session_start();
		}

		public static function open($path,$name) {
			return true;
		}

		public static function close() {
			return true;
		}

		public static function read($id) {
			$data = self::$handle->get(self::getMemSessionName($id));
			//如果无数据
			if($data == false || $data == null) {
				return '';
			}
			return $data;
		}

		public static function write($id,$data) {
			//将数据写入memcache服务器中
			$fun = $data ? 'set' : 'replace';
			return self::$handle->$fun(self::getMemSessionName($id),$data,MEMCACHE_COMPRESSED,self::$lifetime);
		}

		public static function destroy($id) {
			return self::$handle->delete(self::getMemSessionName($id));
		}

		/*
			由于memcache服务器在存储数据时,已经设定失效时间。
			所以不用此函数。
		*/
		public static function gc($maxlifetime) {
			return true;
		}
		
		/*
			获取session名
			前缀+id
		*/
		public static function  getMemSessionName($id) {
			$sessionName = self::NS.$id;
			return $sessionName;
		}

	}

	$mem = new Memcache();
	$mem->connect("localhost","11211") or die("链接memcache服务器出错!");
	MemSession::start($mem);

在one.php,two.php,three.php中加入memcache.class.php

include('memcache.class.php');

执行页面查看memcache服务器

stats items
STAT items:3:number 1
STAT items:3:age 36
STAT items:3:evicted 0
STAT items:3:outofmemory 0
END
stats cachedump 3 0
ITEM memcache_i0ddovbpsi5cp8gm3pktdh9nm5 [34 b; 1523958760 s]
END
get memcache_i0ddovbpsi5cp8gm3pktdh9nm5
VALUE memcache_i0ddovbpsi5cp8gm3pktdh9nm5 0 34
username|s:2:"yc";pwd|s:5:"admin";
END
还可以通过修改php.ini文件中的session.save_handler和session.save_path两个选项,直接将session信息保存到memcache服务器中。
session.save_handler=memcache    
session.save_path=tcp://localhost:11211



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值