1. PHP
的
COOKIE
cookie
是一种在远程浏览器端储存数据并以此来跟踪和识别用户的机制。
PHP
在
http
协议的头信息里发送
cookie,
因此
setcookie
()
函数必须在其它信息被输出到浏览器前调用,这和对
header
()
函数的限制类似。
1.1
设置
cookie:
可以用
setcookie
()
或
setrawcookie
()
函数来设置
cookie
。也可以通过向客户端直接发送
http
头来设置
.
1.1.1
使用
setcookie()
函数设置
cookie:
bool
setcookie
(
string
name [,
string
value [, int expire [,
string
path [,
string
domain [, bool secure [, bool httponly]]]]]] )
name: cookie
变量名
value: cookie
变量的值
expire:
有效期结束的时间
,
path:
有效目录
,
domain:
有效域名
,
顶级域唯一
secure:
如果值为
1,
则
cookie
只能在
https
连接上有效
,
如果为默认值
0,
则
http
和
https
都可以
.
例子
:
<?php
$value
= 'something from somewhere';
setcookie
("TestCookie",
$value
);
/*
简单
cookie
设置
*/
setcookie
("TestCookie",
$value
,
time
()+3600);
/*
有效期
1
个小时
*/
setcookie
("TestCookie",
$value
,
time
()+3600, "/~rasmus/", ".example.com", 1);
/*
有效目录
/~rasmus,
有效域名
example.com
及其所有子域名
*/
?>
设置多个
cookie
变量
:
setcookie
('var[a]','value');
用数组来表示变量
,
但他的下标不用引号
.
这样就可以用
$_COOKIE
[‘
var
’][‘a’]
来读取该
COOKIE
变量
.
1.1.2.
使用
header()
设置
cookie;
header
("Set-Cookie: name=$value[;path=$path[;domain=xxx.com[; ]]");
后面的参数和上面列出
setcookie
函数的参数一样
.
比如
:
$value
= 'something from somewhere';
header
("Set-Cookie:name=$value");
1.2 Cookie
的读取
:
直接用
php
内置超级全局变量
$_COOKIE
就可以读取浏览器端的
cookie
.
上面例子中设置了
cookie"TestCookie",
现在我们来读取
:
print
$_COOKIE
['TestCookie'];
COOKIE
是不是被输出了
?!
1.3
删除
cookie
只需把有效时间设为小于当前时间
,
和把值设置为空
.
例如
:
setcookie
("name","",
time
()-1);
用
header()
类似
.
1.4
常见问题解决
:
1)
用
setcookie()
时有错误提示
,
可能是因为调用
setcookie()
前面有输出或空格
.
也可能你的文档使从其他字符集转换过来
,
文档后面可能带有
BOM
签名
(
就是在文件内容添加一些隐藏的
BOM
字符
).
解决的办法就是使你的文档不出现这种情况
.
还有通过使用
ob_start()
函数有也能处理一点
.
2)
$_COOKIE
受
magic_quotes_gpc
影响
,
可能自动转义
3)
使用的时候
,
有必要测试用户是否支持
cookie
<!--[
if
!supportLineBreakNewLine]-->
1.5 cookie
工作机理
:
有些学习者比较冲动
,
没心思把原理研究
,
所以我把它放后面
.
a)
服务器通过随着响应发送一个
http
的
Set-Cookie
头
,
在客户机中设置一个
cookie(
多个
cookie
要多个头
).
b)
客户端自动向服务器端发送一个
http
的
cookie
头
,
服务器接收读取
.
HTTP/1.x 200 OK
X-Powered-By: PHP/5.2.1
Set-Cookie: TestCookie=something from somewhere; path=/
Expires: Thu, 19 Nov 2007 18:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Content-type: text/html
这一行实现了
cookie
功能
,
收到这行后
Set-Cookie: TestCookie=something from somewhere; path=/
浏览器将在客户端的磁盘上创建一个
cookie
文件
,
并在里面写入
:
TestCookie=something from somewhere;
/
这一行就是我们用
setcookie('TestCookie','something from somewhere','/');
的结果
.
也就是用
header('Set-Cookie: TestCookie=something from somewhere; path=/');
的结果
.
<!--[
endif
]-->
2. PHP
的
Session
session
使用过期时间设为
0
的
cookie,
并且将一个称为
session ID
的唯一标识符
(
一长串字符串
),
在服务器端同步生成一些
session
文件
(
可以自己定义
session
的保存类型
),
与用户机关联起来
.web
应用程序存贮与这些
session
相关的数据
,
并且让数据随着用户在页面之间传递
.
访问网站的来客会被分配一个唯一的标识符,即所谓的会话
ID
。它要么存放在客户端的
cookie
,要么经由
URL
传递。
会话支持允许用户注册任意数目的变量并保留给各个请求使用。当来客访问网站时,
PHP
会自动(如果
session.auto_start
被设为
1
)或在用户请求时(由
session_start
()
明确调用或
session_register
()
暗中调用)检查请求中是否发送了特定的会话
ID
。如果是,则之前保存的环境就被重建。
2.1 sessionID
的传送
2.1.1
通过
cookie
传送
sessin ID
使用
session_start()
调用
session,
服务器端在生成
session
文件的同时
,
生成
session ID
哈希值和默认值为
PHPSESSID
的
session name,
并向客户端发送变量为
(
默认的是
)PHPSESSID(session name),
值为一个
128
位的哈希值
.
服务器端将通过该
cookie
与客户端进行交互
.
session
变量的值经
php
内部系列化后保存在服务器机器上的文本文件中
,
和客户端的变量名默认情况下为
PHPSESSID
的
coolie
进行对应交互
.
即服务器自动发送了
http
头
:
header
('Set-Cookie: session_name()=session_id(); path=/');
即
setcookie(
session_name
(),
session_id
());
当从该页跳转到的新页面并调用
session_start()
后
,PHP
将检查与给定
ID
相关联的服务器端存贮的
session
数据
,
如果没找到
,
则新建一个数据集
.
2.1.2
通过
URL
传送
session ID
只有在用户禁止使用
cookie
的时候才用这种方法
,
因为浏览器
cookie
已经通用
,
为安全起见
,
可不用该方法
.
<a href="p.php?<?php print session_name() ?>=<?php print session_id() ?>">xxx</a>,
也可以通过
POST
来传递
session
值
.
2.2 session
基本用法实例
<?php
// page1.php
session_start
();
echo
'Welcome to page #1';
/*
创建
session
变量并给
session
变量赋值
*/
$_SESSION
['favcolor'] = 'green';
$_SESSION
['animal'] = 'cat';
$_SESSION
['time'] =
time
();
//
如果客户端使用
cookie,
可直接传递
session
到
page2.php
echo
'<br /><a href="page2.php">page 2</a>';
//
如果客户端禁用
cookie
echo
'<br /><a href="page2.php?' . SID . '">page 2</a>';
/*
默认
php5.2.1
下
,SID
只有在
cookie
被写入的同时才会有值
,
如果该
session
对应的
cookie
已经存在
,
那么
SID
将为
(
未定义
)
空
*/
?>
<?php
// page2.php
session_start
();
print
$_SESSION
['animal'];
//
打印出单个
session
var_dump
(
$_SESSION
);
//
打印出
page1.php
传过来的
session
值
?>
2.3
使用
session
函数控制页面缓存
.
很多情况下
,
我们要确定我们的网页是否在客户端缓存
,
或要设置缓存的有效时间
,
比如我们的网页上有些敏感内容并且要登录才能查看
,
如果缓存到本地了
,
可以直接打开本地的缓存就可以不登录而浏览到网页了
.
使用
session_cache_limiter('private');
可以控制页面客户端缓存
,
必须在
session_start()
之前调用
.
更多参数见
http:
//blog.chinaunix.net/u/27731/showart.php?id=258087
的客户端缓存控制
.
控制客户端缓存时间用
session_cache_expire
(int);
单位
(s).
也要在
session_start()
前调用
.
这只是使用
session
的情况下控制缓存的方法
,
我们还可以在
header()
中控制控制页面的缓存
.
2.4
删除
session
要三步实现
.
<?php
session_destroy
();
//
第一步
:
删除服务器端
session
文件
,
这使用
setcookie
(
session_name
(),'',
time
()-3600);
//
第二步
:
删除实际的
session:
$_SESSION
=
array
();
//
第三步
:
删除
$_SESSION
全局变量数组
?>
2.5 session
在
PHP
大型
web
应用中的使用
对于访问量大的站点
,
用默认的
session
存贮方式并不适合
,
目前最优的方法是用数据库存取
session.
这时
,
函数
bool
session_set_save_handler
(
callback
open,
callback
close,
callback
read,
callback
write,
callback
destroy,
callback
gc )
就是提供给我们解决这个问题的方案
.
该函数使用的
6
个函数如下
:
1. bool open()
用来打开会话存储机制
,
2. bool close()
关闭会话存储操作
.
3. mixde read()
从存储中装在
session
数据时使用这个函数
4. bool write()
将给定
session ID
的所有数据写到存储中
5. bool destroy()
破坏与指定的会话
ID
相关联的数据
6. bool gc()
对存储系统中的数据进行垃圾收集
例子见
php
手册
session_set_save_handler()
函数
.
如果用类来处理
,
用
session_set_save_handler
(
array
('className','open'),
array
('className','close'),
array
('className','read'),
array
('className','write'),
array
('className','destroy'),
array
('className','gc'),
)
调用
className
类中的
6
个静态方法
.className
可以换对象就不用调用静态方法
,
但是用静态成员不用生成对象
,
性能更好
.
2.6
常用
session
函数
:
bool
session_start
(void);
初始化
session
bool
session_destroy
(void):
删除服务器端
session
关联文件。
string
session_id
()
当前
session
的
id
string
session_name
()
当前存取的
session
名称
,
也就是客户端保存
session ID
的
cookie
名称
.
默认
PHPSESSID
。
array
session_get_cookie_params
()
与这个
session
相关联的
session
的细节
.
string
session_cache_limiter
()
控制使用
session
的页面的客户端缓存
ini
session_cache_expire
()
控制客户端缓存时间
bool
session_destroy
()
删除服务器端保存
session
信息的文件
void
session_set_cookie_params
( int lifetime [,
string
path [,
string
domain [, bool secure [, bool httponly]]]] )
设置与这个
session
相关联的
session
的细节
bool
session_set_save_handler
(
callback
open,
callback
close,
callback
read,
callback
write,
callback
destroy,
callback
gc )
定义处理
session
的函数
,(
不是使用默认的方式
)
bool
session_regenerate_id
([bool delete_old_session])
分配新的
session id
2.7 session
安全问题
攻击者通过投入很大的精力尝试获得现有用户的有效会话
ID,
有了会话
id,
他们就有可能能够在系统中拥有与此用户相同的能力
.
因此
,
我们主要解决的思路是效验
session ID
的有效性
.
<?php
if
(!
isset
(
$_SESSION
['user_agent'])){
$_SESSION
['user_agent'] =
$_SERVER
['REMOTE_ADDR'].
$_SERVER
['HTTP_USER_AGENT'];
}
/*
如果用户
session ID
是伪造
*/
elseif
(
$_SESSION
['user_agent'] !=
$_SERVER
['REMOTE_ADDR'] .
$_SERVER
['HTTP_USER_AGENT']) {
session_regenerate_id
();
}
?>
2.8 Session
通过
cookie
传递和通过
SID
传递的不同
:
在
php5.2.1
的
session
的默认配置的情况下
,
当生成
session
的同时
,
服务器端将在发送
header set-cookie
同时生成预定义超级全局变量
SID(
也就是说
,
写入
cookie
和抛出
SID
是等价的
.),
当
$_COOKIE
['PHPSESSID']
存在以后
,
将不再写入
cookie,
也不再生成超级全局变量
SID,
此时
,SID
将是空的
.
2.9 session
使用实例
<?php
/**
*
效验
session
的合法性
*
*/
function
sessionVerify() {
if
(!
isset
(
$_SESSION
['user_agent'])){
$_SESSION
['user_agent'] =
MD5
(
$_SERVER
['REMOTE_ADDR']
.
$_SERVER
['HTTP_USER_AGENT']);
}
/*
如果用户
session ID
是伪造
,
则重新分配
session ID */
elseif
(
$_SESSION
['user_agent'] !=
MD5
(
$_SERVER
['REMOTE_ADDR']
.
$_SERVER
['HTTP_USER_AGENT'])) {
session_regenerate_id
();
}
}
/**
*
销毁
session
*
三步完美实现
,
不可漏
*
*/
function
sessionDestroy() {
session_destroy
();
setcookie
(
session_name
(),'',
time
()-3600);
$_SESSION
=
array
();
}
?>
注明
:
session
出现头信息已经发出的原因与
cookie
一样
.
在
php5
中
,
所有
php session
的注册表配置选项都是编程时可配置的
,
一般情况下
,
我们是不用修改其配置的
.
要了解
php
的
session
注册表配置选项
,
请参考手册的
Session
会话处理函数处
.
session
的保存数据的时候,是通过系列化
$_SESSION
数组来存贮
,所以有系列化所拥有的问题,可能有特殊字符的值要用
base64_encode
函数编码,读取的时候再用
base64_decode
解码