<?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');
<?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