session使用方法
时间:2008-07-04 来源:sinkingboat
在
[color="#3399cc"]PHP
开发中对比起Cookie,
[color="#3399cc"]session
是存储在服务器端的会话,相对安全,并且不像 Cookie 那样有存储长度限制,本文简单介绍
[color="#3399cc"]session
的使用。
\Z.h?;r2g!q/N31737
'kT$S1\x.nqb31737 由于 Session 是以文本文件形式存储在服务器端的,所以不怕客户端修改 Session 内容。实际上在服务器端的 Session 文件,PHP 自动修改
[color="#3399cc"]session
文件的权限,只保留了系统读和写权限,而且不能通过 ftp 修改,所以安全得多。
[color="#3399cc"]PHP
China
[url=javascript:;][color="#009999"]开源[/url]
社区门户k%W%e2CY
yA'oOtD31737PHPChina 开源社区门户?+s9|:h7a
对于 Cookie 来说,假设我们要验证用户是否登陆,就必须在 Cookie 中保存用户名和密码(可能是 md5 加密后字符串),并在每次请求页面的时候进行验证。如果用户名和密码存储在
[url=javascript:;][color="#009999"]数据库[/url]
,每次都要执行一次数据库查询,给
[color="#3399cc"]数据库
造
成多余的负担。因为我们并不能 只做一次验证。为什么呢?因为客户端 Cookie 中的信息是有可能被修改的。假如你存储 $admin
变量来表示用户是否登陆,$admin 为 true 的时候表示登陆,为 false 的时候表示未登录,在第一次通过验证后将 $admin 等于
true 存储在 Cookie,下次就不用验证了,这样对么?错了,假如有人伪造一个值为 true 的 $admin
变量那不是就立即取的了管理权限么?非常的不安全。
5KZb%c_pC31737
kk-N3FBlz[}R31737 而 Session 就不同了,Session 是存储在服务器端的,远程用户没办法修改
[color="#3399cc"]session
文件的内容,因此我们可以单纯存储一个 $admin 变量来判断是否登陆,首次验证通过后设置 $admin 值为 true,以后判断该值是否为 true,假如不是,转入登陆界面,这样就可以减少很多
[color="#3399cc"]数据库
操作了。而且可以减少每次为了验证 Cookie 而传递密码的不安全性了(
[color="#3399cc"]session
验证只需要传递一次,假如你没有使用 SSL 安全协议的话)。即使密码进行了 md5 加密,也是很容易被截获的。PHPChina 开源社区门户 K"i(@8ij#{\ F ~,S
PHPChina 开源社区门户-Z.F K;m+K8s.Z+_
当然使用
[color="#3399cc"]session
还有很多优点,比如控制容易,可以按照用户自定义存储等(存储于
[color="#3399cc"]数据库
)。我这里就不多说了。
p noyw u31737
6\ Ni*f`nm31737
[color="#3399cc"]session
在 php.ini 是否需要设置呢?一般不需要的,因为并不是每个人都有修改
[color="#3399cc"]PHP
.ini 的权限,默认
[color="#3399cc"]session
的存放路径是服务器的系统临时文件夹,我们可以自定义存放在自己的文件夹里,这个稍后我会介绍。
!sr[ f,Avg`31737
&C Jj!c!aV6TL31737 开始介绍如何创建
[color="#3399cc"]session
。非常简单,真的。
.KRM.S/u ]r31737
H?SA!a*Uu31737 启动
[color="#3399cc"]session
会话,并创建一个 $admin 变量:
+T ?}t%|*a9z}4OJ31737PHPChina 开源社区门户V3L YtlTq(s~
<?
[color="#3399cc"]PHP
PHPChina 开源社区门户!Q[$R(U si#@(w
// 启动
[color="#3399cc"]session
PHPChina 开源社区门户 S6XL0Q#I/S J ]
[color="#3399cc"]session
_start();
6Xd*z0m-d`%Yn.|31737// 声明一个名为 admin 的变量,并赋空值。PHPChina 开源社区门户OT?t!ir
$_
[color="#3399cc"]session
["admin"] = null; PHPChina 开源社区门户!d%R6Q%W6~(Im)J/cA
?>
ef;|(JY#W)Z{31737 如果你使用了 Seesion,或者该 PHP 文件要调用 Session 变量,那么就必须在调用 Session 之前启动它,使用
[color="#3399cc"]session
_start()
[color="#3399cc"]函数
。其它都不需要你设置了,
[color="#3399cc"]PHP
自动完成
[color="#3399cc"]session
文件的创建。
~S$M"\2K'rr31737PHPChina 开源社区门户.eX"p]5}3`
执行完这个程序后,我们可以到系统临时文件夹找到这个
[color="#3399cc"]session
文件,一般文件名形如:sess_4c83638b3b0dbf65583181c2f89168ec,后面是 32 位编码后的随机字符串。用编辑器打开它,看一下它的内容:
v/LPz)~%s2AK31737
2]3@$tFy { S!~ P31737 admin|N;
VIO}^.n"C1\31737PHPChina 开源社区门户k J"jD Dg)q3kJ.z?}
一般该内容是这样的结构:PHPChina 开源社区门户"|e Bam[ x\5|Y([,O-[a
PHPChina 开源社区门户!D"m(T:a9Q)? q
变量名|类型:长度:值;
}yP"b'cU%k/V31737PHPChina 开源社区门户 i nH^d l$Gf/n|)r
并用分号隔开每个变量。有些是可以省略的,比如长度和类型。PHPChina 开源社区门户6`/W!wA*_L;Y8~&U
PHPChina 开源社区门户b/H#JTt+[
我们来看一下验证程序,假设
[color="#3399cc"]数据库
存储的是用户名和 md5 加密后的密码:PHPChina 开源社区门户)m9xFe[ {
1g$VEN&K KR@31737
<?
[color="#3399cc"]PHP
PHPChina 开源社区门户8d q5s_ {d
$@)m!By%[iI@m31737// 表单提交后...
m2q!ej3e!`31737$posts = $_POST;
6?@[6J MQ$u31737// 清除一些空白符号
#W:e:b.l-C31737foreach ($posts as $key => $value)PHPChina 开源社区门户*yb*ycu ]"_|
{PHPChina 开源社区门户t,aE hyE2T/W?
$posts[$key] = trim($value); PHPChina 开源社区门户cw%L4Ie%B}
}
F1n)N [1w}f/N31737$password = md5($posts["password"]);
t*tV&bF*ISa,B31737$username = $posts["username"]; PHPChina 开源社区门户Q.I!Hk9t eh
CAtW3yBM31737$query = "SELECT `username` FROM `user` WHERE `password` = '$password'"; PHPChina 开源社区门户t,?#\*I \P
// 取得查询结果
\8J2]-y{31737$userInfo = $DB->getRow($query); PHPChina 开源社区门户JV2[T(W%s}#g~v+N
PHPChina 开源社区门户K#m7v^W0c@
if (!empty($userInfo))
!`U-v7} K31737{ PHPChina 开源社区门户8_RQ8n0^3Sr7l'v Q
if ($userInfo["username"] == $username) PHPChina 开源社区门户vF.K#a|so7Yl
{ PHPChina 开源社区门户6Z"~^-vXl*~k
// 当验证通过后,启动
[color="#3399cc"]session
PHPChina 开源社区门户$FWP VW oQ2g~
[color="#3399cc"]session
_start(); PHPChina 开源社区门户 I'HW9JC%Z#^
// 注册登陆成功的 admin 变量,并赋值 true PHPChina 开源社区门户'Cx,uL*SN,x+`.Q
$_
[color="#3399cc"]session
["admin"] = true; PHPChina 开源社区门户.W/I'n/bPR
}
/?+t6AuN#xT31737elsePHPChina 开源社区门户)E%y?6~d r4Z`{
{
9P T%Les31737die("用户名密码错误");
-uQ/g?wW|8i31737} PHPChina 开源社区门户!R-`w9o5A#M#Gc9m]
}
c/@!B2mo31737elsePHPChina 开源社区门户i3H}"b$KX0t
{
Z+{b!\3n&Iby!\31737die("用户名密码错误");
BiL+Y1]A31737}
PHPChina 开源社区门户,O$u~PO/O|
我们在需要用户验证的页面启动
[color="#3399cc"]session
,判断是否登陆:
jF)mde|O?k31737PHPChina 开源社区门户&zlz*_FSz
<?
[color="#3399cc"]PHP
PHPChina 开源社区门户"w*pf9N w
// 防止全局变量造成安全隐患
dk8^I"m5GV6M }w H!A31737$admin = false;
P Fi x,Sfu[31737
H:?U](Y31737// 启动会话,这步必不可少 PHPChina 开源社区门户{aA@'i,g.KA:o
[color="#3399cc"]session
_start();
zd8n(hGCR31737
2kUxZ,gf+j31737// 判断是否登陆 PHPChina 开源社区门户|O D^qEuqe@
if (isset($_SESSION["admin"]) && $_
[color="#3399cc"]session
["admin"] === true) PHPChina 开源社区门户yD'AWM+Mf!t2D
{
:B-yb2c s/~q31737echo "您已经成功登陆";
Txg P@_Kq*H!K31737}
4n2Kl3vYq8Q31737else PHPChina 开源社区门户7s&K7xTW4JV*TqZ
{
e%F2_6o1_b hy/[31737// 验证失败,将 $_
[color="#3399cc"]session
["admin"] 置为 false
$M*U.m.F#r.c7^3S:g31737$_
[color="#3399cc"]session
["admin"] = false; PHPChina 开源社区门户-J;oO,[-gdY `
die("您无权访问"); PHPChina 开源社区门户N\G'U.KN [/{
}
U];KAd-E.vN@31737
kt1SY3a[S"K.R:Z31737?>
u[kn|q)w.x"rB31737 是不是很简单呢?将 $_
[color="#3399cc"]session
看成是存储在服务器端的数组即可,我们注册的每一个变量都是数组的键,跟使用数组没有什么分别。
6v3mnl!K,?a31737PHPChina 开源社区门户 O|*E5vh c,D^-y;}
如果要登出系统怎么办?销毁
[color="#3399cc"]session
即可。
!si`!q$V&sH$YD#C31737PHPChina 开源社区门户4\vPB7|L/Ydi
<?
[color="#3399cc"]PHP
PHPChina 开源社区门户1B\5Y;Li"l ?5^
;Qlzt)km)I4IPv31737
[color="#3399cc"]session
_start();
TAFIfE31737// 这种
[url=javascript:;][color="#009999"]方法[/url]
是将原来注册的某个变量销毁
!v}.CQ`9?O1r31737unset($_
[color="#3399cc"]session
["admin"]);
Oq/\2RJ h31737// 这种方法是销毁整个
[color="#3399cc"]session
文件
)M(Y B;iaw8M.b!M31737
[color="#3399cc"]session
_destroy();
DcpfPcT(F%b,{31737>
PHPChina 开源社区门户ru1@3v"vgUG8j
Session 能否像 Cookie 那样设置生存周期呢?有了 Session 是否就完全抛弃 Cookie 呢?我想说,结合 Cookie 来使用
[color="#3399cc"]session
才是最方便的。
!ct a4^V31737PHPChina 开源社区门户(q2`/m7Z2K^
Session 是如何来判断客户端用户的呢?它是通过 Session ID 来判断的,什么是 Session ID,就是那个 Session
文件的文件名,Session ID 是随机生成的,因此能保证唯一性和随机性,确保 Session 的安全。一般如果没有设置 Session
的生存周期,则 Session ID 存储在内存中,关闭浏览器后该 ID 自动注销,重新请求该页面后,重新注册一个
[color="#3399cc"]session
ID。
w6F1Q%{^31737PHPChina 开源社区门户 q:ZhT:Ja
如果客户端没有禁用 Cookie,则 Cookie 在启动 Session 会话的时候扮演的是存储 Session ID 和
[color="#3399cc"]session
生存期的角色。PHPChina 开源社区门户ru"c7?np_
6R{~?J2i$F31737 我们来手动设置
[color="#3399cc"]session
的生存期:
'j&m,X @BUR0D31737
oyU:sIZ![31737
<?
[color="#3399cc"]PHP
PHPChina 开源社区门户Fn } U_'iI
[color="#3399cc"]session
_start();
Nz6A'\9l[q S*X31737// 保存一天 PHPChina 开源社区门户r`+b\x_C
$lifeTime = 24 * 3600;
Dg9L|&J+m%@31737setcookie(session_name(),
[color="#3399cc"]session
_id(), time() + $lifeTime, "/");
p0Pyd USxu8_31737?>
5fV]~!U]B31737 其实 Session 还提供了一个函数 session_set_cookie_params(); 来设置 Session 的生存期的,该
[color="#3399cc"]函数
必须在
[color="#3399cc"]session
_start()
[color="#3399cc"]函数
调用之前调用:
OJ e@2pW7~#r ff0@7o31737
'H!}nmnx!O1n6vi31737
<?
[color="#3399cc"]PHP
y,P Fpr^31737
;P yi%\@ P31737// 保存一天 PHPChina 开源社区门户"H!BVA:n`Y3q)`
$lifeTime = 24 * 3600; PHPChina 开源社区门户TM2kK;? ^
[color="#3399cc"]session
_set_cookie_params($lifeTime);
+v(||&XCUp!B*O31737
[color="#3399cc"]session
_start();
$n&Z;|HaL31737$_
[color="#3399cc"]session
["admin"] = true;
U$hGfSL&hl31737?>
f4N+l:zSH3L31737 如果客户端使用 IE 6.0 ,
[color="#3399cc"]session
_set_cookie_params(); 函数设置 Cookie 会有些问题,所以我们还是手动调用 setcookie
[color="#3399cc"]函数
来创建 cookie。
*y/V*@Q bH31737
S$~l,k"[ o31737 假设客户端禁用 Cookie 怎么办?没办法,所有生存周期都是浏览器进程了,只要关闭浏览器,再次请求页面又得重新注册 Session。那么怎么传递 Session ID 呢?通过 URL 或者通过隐藏表单来传递,PHP 会自动将
[color="#3399cc"]session
ID 发送到 URL 上,URL 形如:http://www.openphp.cn/index.php?PHPSESSID=bba5b2a240a77e5b44cfa01d49cf9669,其中 URL 中的参数
[color="#3399cc"]PHP
SESSID 就是 Session ID了,我们可以使用 $_GET 来获取该值,从而实现
[color="#3399cc"]session
ID 页面间传递。
c}e3C Z}_31737
[$TW-H"^3F31737
<?
[color="#3399cc"]PHP
qB9w;~2Aaq31737
VwpI$D-y8vp31737// 保存一天 PHPChina 开源社区门户{ MM'p f;M
$lifeTime = 24 * 3600;PHPChina 开源社区门户|2zVb#FX3?g]
// 取得当前
[color="#3399cc"]session
名,默认为
[color="#3399cc"]PHP
SESSID PHPChina 开源社区门户{SJ/t&~CU }\
$sessionName =
[color="#3399cc"]session
_name();
#Cy` rT^d;Ae31737// 取得
[color="#3399cc"]session
ID
Hs'}#T+Nd(T,Q5Q [31737$sessionID = $_GET[$
[color="#3399cc"]session
Name]; PHPChina 开源社区门户 N;Mo6U&||1_
// 使用 session_id() 设置获得的
[color="#3399cc"]session
ID PHPChina 开源社区门户D(`~L a
session_id($
[color="#3399cc"]session
ID); PHPChina 开源社区门户w6f({:VZ-j zj w$q!es
PHPChina 开源社区门户3ZLn7dny0{
[color="#3399cc"]session
_set_cookie_params($lifeTime); PHPChina 开源社区门户0fg4XnjoP*?
[color="#3399cc"]session
_start();PHPChina 开源社区门户#?h[z ^e Baq
$_
[color="#3399cc"]session
["admin"] = true;PHPChina 开源社区门户7d;A,bX:k CJj6|1j
?>
PHPChina 开源社区门户3wlvw wf+CB6[i
对于虚拟主机来说,如果所有用户的 Session 都保存在系统临时文件夹里,将给维护造成困难,而且降低了安全性,我们可以手动设置 Session 文件的保存路径,session_save_path()就提供了这样一个功能。我们可以将
[color="#3399cc"]session
存放目录指向一个不能通过 Web 方式访问的文件夹,当然,该文件夹必须具备可读写
[color="#3399cc"]属性
。PHPChina 开源社区门户%k |7U@6g K Y6B
&jf:}#Q[Z*UPs8l&sH31737
<?
[color="#3399cc"]PHP
PHPChina 开源社区门户TC0y@T)e
// 设置一个存放目录
p%w2TB1y-a O ^31737$savePath = "./
[color="#3399cc"]session
_save_dir/"; PHPChina 开源社区门户Hq)E#yE9Vs&| q'zV
// 保存一天 PHPChina 开源社区门户#T$Ug:Q|;VIB
$lifeTime = 24 * 3600; PHPChina 开源社区门户Z8fu7[$N `Z5K9P
[color="#3399cc"]session
_save_path($savePath);
)f*r$KA"p#yx"tIt31737
[color="#3399cc"]session
_set_cookie_params($lifeTime);
4A6k5@T2o7j F _&^%@%` d31737
[color="#3399cc"]session
_start();
U2Q M;J.@([z4y31737$_
[color="#3399cc"]session
["admin"] = true;
4h{/i5Doe}n9gi_ |-n$q31737?>
PHPChina 开源社区门户^j3R/F%_;Gj:eV H
同 session_set_cookie_params(); 函数一样,session_save_path()
[color="#3399cc"]函数
也必须在
[color="#3399cc"]session
_start()
[color="#3399cc"]函数
调用之前调用。
M.f't8Ul[ \ q31737
`W8JI/S)g31737 我们还可以将数组,
[url=javascript:;][color="#009999"]对象[/url]
存储在
[color="#3399cc"]session
中。操作数组和操作一般变量没有什么区别,而保存对象的话,
[color="#3399cc"]PHP
会自动对对象进行序列化(也叫串行化),然后保存于
[color="#3399cc"]session
中。下面例子说明了这一点:
^,K)?*m {*E9s3e f31737
`2];ZMl31737
<?
[color="#3399cc"]PHP
/j|3} W E @31737class person PHPChina 开源社区门户!B8[ q,}~k$|1n*U2{7A [ E`
{
NK5c(]%]3X31737var $age; PHPChina 开源社区门户b3e&o1W3H o'Yxt:}4j Z)S
function output() { PHPChina 开源社区门户Bb0[&S(tI
echo $this->age;
#@'{0lc'Cz31737} PHPChina 开源社区门户X _?WF(hk7o
PHPChina 开源社区门户2K?5A D Mv#x5z
function setAge($age) { PHPChina 开源社区门户9S5Z$oEu[7@3?S
$this->age = $age; PHPChina 开源社区门户d0E/[ b H;R
}
R$g| Q&E)|z31737} PHPChina 开源社区门户'i R`S"|
?>PHPChina 开源社区门户%f.Vdr;e D9c Z%|
setage.
[color="#3399cc"]PHP
PHPChina 开源社区门户:m-]S7h&K9d
<?
[color="#3399cc"]PHP
PHPChina 开源社区门户9\;C2d c6? B5N]
[color="#3399cc"]session
_start(); PHPChina 开源社区门户 QHB}aWi4L
require_once "person.
[color="#3399cc"]PHP
"; PHPChina 开源社区门户9zmsl ~)C r
$person = new person(); PHPChina 开源社区门户 Y,V \"{6BUUL*x$x
$person->setAge(21);
-QA*V7K[V C-qu31737$_
[color="#3399cc"]session
['person'] = $person;
bQ5aeCQ31737echo "<a href='output'>check here to output age</a>";
:Yc9~+W$s)cxb31737?>PHPChina 开源社区门户!VCQ,Q~U{~ l^kP$?
output.
[color="#3399cc"]PHP
m:h FI&r})n31737<?
/[(br`9J4b3K!B31737// 设置回调
[color="#3399cc"]函数
,确保重新构建对象。
Z/\8PR+e31737ini_set('unserialize_callback_func', 'mycallback'); PHPChina 开源社区门户 l'D7m9}|Y
function mycallback($classname) { PHPChina 开源社区门户 _&Uu&H0H$c'm0u+UG
$classname . ".
[color="#3399cc"]PHP
"; PHPChina 开源社区门户"Z9A&D.mS6^]3ev
}PHPChina 开源社区门户p0R x*v#dn&T$u
[color="#3399cc"]session
_start();PHPChina 开源社区门户UOr2K A3N
$person = $_
[color="#3399cc"]session
["person"];
6RCCD$wt uP-P31737// 输出 21 PHPChina 开源社区门户k|'X(`mo
$person->output();
g eh"yuy31737?>
PHPChina 开源社区门户[~z9|]yiy5f+b D t
当我们执行 setage.php 文件的时候,调用了 setage() 方法,设置了年龄为 21,并将该状态序列化后保存在
[color="#3399cc"]session
中(PHP 将自动完成这一转换),当转到 output.php 后,要输出这个值,就必须反序列化刚才保存的对象,又因为在解序列化的时候需要实例化一个未定义类,所以我们定义了以后回调
[color="#3399cc"]函数
,自动包含 person.
[color="#3399cc"]PHP
这个类文件,因此对象被重构,并取得当前 age 的值为 21,然后调用 output() 方法输出该值。PHPChina 开源社区门户?$Bw zc
'm IE2MM31737 另外,我们还可以使用 session_set_save_handler
[color="#3399cc"]函数
来自定义
[color="#3399cc"]session
的调用方式。
[color="#3399cc"]PHP
开发中对比起Cookie,
[color="#3399cc"]session
是存储在服务器端的会话,相对安全,并且不像 Cookie 那样有存储长度限制,本文简单介绍
[color="#3399cc"]session
的使用。
\Z.h?;r2g!q/N31737
'kT$S1\x.nqb31737 由于 Session 是以文本文件形式存储在服务器端的,所以不怕客户端修改 Session 内容。实际上在服务器端的 Session 文件,PHP 自动修改
[color="#3399cc"]session
文件的权限,只保留了系统读和写权限,而且不能通过 ftp 修改,所以安全得多。
[color="#3399cc"]PHP
China
[url=javascript:;][color="#009999"]开源[/url]
社区门户k%W%e2CY
yA'oOtD31737PHPChina 开源社区门户?+s9|:h7a
对于 Cookie 来说,假设我们要验证用户是否登陆,就必须在 Cookie 中保存用户名和密码(可能是 md5 加密后字符串),并在每次请求页面的时候进行验证。如果用户名和密码存储在
[url=javascript:;][color="#009999"]数据库[/url]
,每次都要执行一次数据库查询,给
[color="#3399cc"]数据库
造
成多余的负担。因为我们并不能 只做一次验证。为什么呢?因为客户端 Cookie 中的信息是有可能被修改的。假如你存储 $admin
变量来表示用户是否登陆,$admin 为 true 的时候表示登陆,为 false 的时候表示未登录,在第一次通过验证后将 $admin 等于
true 存储在 Cookie,下次就不用验证了,这样对么?错了,假如有人伪造一个值为 true 的 $admin
变量那不是就立即取的了管理权限么?非常的不安全。
5KZb%c_pC31737
kk-N3FBlz[}R31737 而 Session 就不同了,Session 是存储在服务器端的,远程用户没办法修改
[color="#3399cc"]session
文件的内容,因此我们可以单纯存储一个 $admin 变量来判断是否登陆,首次验证通过后设置 $admin 值为 true,以后判断该值是否为 true,假如不是,转入登陆界面,这样就可以减少很多
[color="#3399cc"]数据库
操作了。而且可以减少每次为了验证 Cookie 而传递密码的不安全性了(
[color="#3399cc"]session
验证只需要传递一次,假如你没有使用 SSL 安全协议的话)。即使密码进行了 md5 加密,也是很容易被截获的。PHPChina 开源社区门户 K"i(@8ij#{\ F ~,S
PHPChina 开源社区门户-Z.F K;m+K8s.Z+_
当然使用
[color="#3399cc"]session
还有很多优点,比如控制容易,可以按照用户自定义存储等(存储于
[color="#3399cc"]数据库
)。我这里就不多说了。
p noyw u31737
6\ Ni*f`nm31737
[color="#3399cc"]session
在 php.ini 是否需要设置呢?一般不需要的,因为并不是每个人都有修改
[color="#3399cc"]PHP
.ini 的权限,默认
[color="#3399cc"]session
的存放路径是服务器的系统临时文件夹,我们可以自定义存放在自己的文件夹里,这个稍后我会介绍。
!sr[ f,Avg`31737
&C Jj!c!aV6TL31737 开始介绍如何创建
[color="#3399cc"]session
。非常简单,真的。
.KRM.S/u ]r31737
H?SA!a*Uu31737 启动
[color="#3399cc"]session
会话,并创建一个 $admin 变量:
+T ?}t%|*a9z}4OJ31737PHPChina 开源社区门户V3L YtlTq(s~
<?
[color="#3399cc"]PHP
PHPChina 开源社区门户!Q[$R(U si#@(w
// 启动
[color="#3399cc"]session
PHPChina 开源社区门户 S6XL0Q#I/S J ]
[color="#3399cc"]session
_start();
6Xd*z0m-d`%Yn.|31737// 声明一个名为 admin 的变量,并赋空值。PHPChina 开源社区门户OT?t!ir
$_
[color="#3399cc"]session
["admin"] = null; PHPChina 开源社区门户!d%R6Q%W6~(Im)J/cA
?>
ef;|(JY#W)Z{31737 如果你使用了 Seesion,或者该 PHP 文件要调用 Session 变量,那么就必须在调用 Session 之前启动它,使用
[color="#3399cc"]session
_start()
[color="#3399cc"]函数
。其它都不需要你设置了,
[color="#3399cc"]PHP
自动完成
[color="#3399cc"]session
文件的创建。
~S$M"\2K'rr31737PHPChina 开源社区门户.eX"p]5}3`
执行完这个程序后,我们可以到系统临时文件夹找到这个
[color="#3399cc"]session
文件,一般文件名形如:sess_4c83638b3b0dbf65583181c2f89168ec,后面是 32 位编码后的随机字符串。用编辑器打开它,看一下它的内容:
v/LPz)~%s2AK31737
2]3@$tFy { S!~ P31737 admin|N;
VIO}^.n"C1\31737PHPChina 开源社区门户k J"jD Dg)q3kJ.z?}
一般该内容是这样的结构:PHPChina 开源社区门户"|e Bam[ x\5|Y([,O-[a
PHPChina 开源社区门户!D"m(T:a9Q)? q
变量名|类型:长度:值;
}yP"b'cU%k/V31737PHPChina 开源社区门户 i nH^d l$Gf/n|)r
并用分号隔开每个变量。有些是可以省略的,比如长度和类型。PHPChina 开源社区门户6`/W!wA*_L;Y8~&U
PHPChina 开源社区门户b/H#JTt+[
我们来看一下验证程序,假设
[color="#3399cc"]数据库
存储的是用户名和 md5 加密后的密码:PHPChina 开源社区门户)m9xFe[ {
1g$VEN&K KR@31737
<?
[color="#3399cc"]PHP
PHPChina 开源社区门户8d q5s_ {d
$@)m!By%[iI@m31737// 表单提交后...
m2q!ej3e!`31737$posts = $_POST;
6?@[6J MQ$u31737// 清除一些空白符号
#W:e:b.l-C31737foreach ($posts as $key => $value)PHPChina 开源社区门户*yb*ycu ]"_|
{PHPChina 开源社区门户t,aE hyE2T/W?
$posts[$key] = trim($value); PHPChina 开源社区门户cw%L4Ie%B}
}
F1n)N [1w}f/N31737$password = md5($posts["password"]);
t*tV&bF*ISa,B31737$username = $posts["username"]; PHPChina 开源社区门户Q.I!Hk9t eh
CAtW3yBM31737$query = "SELECT `username` FROM `user` WHERE `password` = '$password'"; PHPChina 开源社区门户t,?#\*I \P
// 取得查询结果
\8J2]-y{31737$userInfo = $DB->getRow($query); PHPChina 开源社区门户JV2[T(W%s}#g~v+N
PHPChina 开源社区门户K#m7v^W0c@
if (!empty($userInfo))
!`U-v7} K31737{ PHPChina 开源社区门户8_RQ8n0^3Sr7l'v Q
if ($userInfo["username"] == $username) PHPChina 开源社区门户vF.K#a|so7Yl
{ PHPChina 开源社区门户6Z"~^-vXl*~k
// 当验证通过后,启动
[color="#3399cc"]session
PHPChina 开源社区门户$FWP VW oQ2g~
[color="#3399cc"]session
_start(); PHPChina 开源社区门户 I'HW9JC%Z#^
// 注册登陆成功的 admin 变量,并赋值 true PHPChina 开源社区门户'Cx,uL*SN,x+`.Q
$_
[color="#3399cc"]session
["admin"] = true; PHPChina 开源社区门户.W/I'n/bPR
}
/?+t6AuN#xT31737elsePHPChina 开源社区门户)E%y?6~d r4Z`{
{
9P T%Les31737die("用户名密码错误");
-uQ/g?wW|8i31737} PHPChina 开源社区门户!R-`w9o5A#M#Gc9m]
}
c/@!B2mo31737elsePHPChina 开源社区门户i3H}"b$KX0t
{
Z+{b!\3n&Iby!\31737die("用户名密码错误");
BiL+Y1]A31737}
PHPChina 开源社区门户,O$u~PO/O|
我们在需要用户验证的页面启动
[color="#3399cc"]session
,判断是否登陆:
jF)mde|O?k31737PHPChina 开源社区门户&zlz*_FSz
<?
[color="#3399cc"]PHP
PHPChina 开源社区门户"w*pf9N w
// 防止全局变量造成安全隐患
dk8^I"m5GV6M }w H!A31737$admin = false;
P Fi x,Sfu[31737
H:?U](Y31737// 启动会话,这步必不可少 PHPChina 开源社区门户{aA@'i,g.KA:o
[color="#3399cc"]session
_start();
zd8n(hGCR31737
2kUxZ,gf+j31737// 判断是否登陆 PHPChina 开源社区门户|O D^qEuqe@
if (isset($_SESSION["admin"]) && $_
[color="#3399cc"]session
["admin"] === true) PHPChina 开源社区门户yD'AWM+Mf!t2D
{
:B-yb2c s/~q31737echo "您已经成功登陆";
Txg P@_Kq*H!K31737}
4n2Kl3vYq8Q31737else PHPChina 开源社区门户7s&K7xTW4JV*TqZ
{
e%F2_6o1_b hy/[31737// 验证失败,将 $_
[color="#3399cc"]session
["admin"] 置为 false
$M*U.m.F#r.c7^3S:g31737$_
[color="#3399cc"]session
["admin"] = false; PHPChina 开源社区门户-J;oO,[-gdY `
die("您无权访问"); PHPChina 开源社区门户N\G'U.KN [/{
}
U];KAd-E.vN@31737
kt1SY3a[S"K.R:Z31737?>
u[kn|q)w.x"rB31737 是不是很简单呢?将 $_
[color="#3399cc"]session
看成是存储在服务器端的数组即可,我们注册的每一个变量都是数组的键,跟使用数组没有什么分别。
6v3mnl!K,?a31737PHPChina 开源社区门户 O|*E5vh c,D^-y;}
如果要登出系统怎么办?销毁
[color="#3399cc"]session
即可。
!si`!q$V&sH$YD#C31737PHPChina 开源社区门户4\vPB7|L/Ydi
<?
[color="#3399cc"]PHP
PHPChina 开源社区门户1B\5Y;Li"l ?5^
;Qlzt)km)I4IPv31737
[color="#3399cc"]session
_start();
TAFIfE31737// 这种
[url=javascript:;][color="#009999"]方法[/url]
是将原来注册的某个变量销毁
!v}.CQ`9?O1r31737unset($_
[color="#3399cc"]session
["admin"]);
Oq/\2RJ h31737// 这种方法是销毁整个
[color="#3399cc"]session
文件
)M(Y B;iaw8M.b!M31737
[color="#3399cc"]session
_destroy();
DcpfPcT(F%b,{31737>
PHPChina 开源社区门户ru1@3v"vgUG8j
Session 能否像 Cookie 那样设置生存周期呢?有了 Session 是否就完全抛弃 Cookie 呢?我想说,结合 Cookie 来使用
[color="#3399cc"]session
才是最方便的。
!ct a4^V31737PHPChina 开源社区门户(q2`/m7Z2K^
Session 是如何来判断客户端用户的呢?它是通过 Session ID 来判断的,什么是 Session ID,就是那个 Session
文件的文件名,Session ID 是随机生成的,因此能保证唯一性和随机性,确保 Session 的安全。一般如果没有设置 Session
的生存周期,则 Session ID 存储在内存中,关闭浏览器后该 ID 自动注销,重新请求该页面后,重新注册一个
[color="#3399cc"]session
ID。
w6F1Q%{^31737PHPChina 开源社区门户 q:ZhT:Ja
如果客户端没有禁用 Cookie,则 Cookie 在启动 Session 会话的时候扮演的是存储 Session ID 和
[color="#3399cc"]session
生存期的角色。PHPChina 开源社区门户ru"c7?np_
6R{~?J2i$F31737 我们来手动设置
[color="#3399cc"]session
的生存期:
'j&m,X @BUR0D31737
oyU:sIZ![31737
<?
[color="#3399cc"]PHP
PHPChina 开源社区门户Fn } U_'iI
[color="#3399cc"]session
_start();
Nz6A'\9l[q S*X31737// 保存一天 PHPChina 开源社区门户r`+b\x_C
$lifeTime = 24 * 3600;
Dg9L|&J+m%@31737setcookie(session_name(),
[color="#3399cc"]session
_id(), time() + $lifeTime, "/");
p0Pyd USxu8_31737?>
5fV]~!U]B31737 其实 Session 还提供了一个函数 session_set_cookie_params(); 来设置 Session 的生存期的,该
[color="#3399cc"]函数
必须在
[color="#3399cc"]session
_start()
[color="#3399cc"]函数
调用之前调用:
OJ e@2pW7~#r ff0@7o31737
'H!}nmnx!O1n6vi31737
<?
[color="#3399cc"]PHP
y,P Fpr^31737
;P yi%\@ P31737// 保存一天 PHPChina 开源社区门户"H!BVA:n`Y3q)`
$lifeTime = 24 * 3600; PHPChina 开源社区门户TM2kK;? ^
[color="#3399cc"]session
_set_cookie_params($lifeTime);
+v(||&XCUp!B*O31737
[color="#3399cc"]session
_start();
$n&Z;|HaL31737$_
[color="#3399cc"]session
["admin"] = true;
U$hGfSL&hl31737?>
f4N+l:zSH3L31737 如果客户端使用 IE 6.0 ,
[color="#3399cc"]session
_set_cookie_params(); 函数设置 Cookie 会有些问题,所以我们还是手动调用 setcookie
[color="#3399cc"]函数
来创建 cookie。
*y/V*@Q bH31737
S$~l,k"[ o31737 假设客户端禁用 Cookie 怎么办?没办法,所有生存周期都是浏览器进程了,只要关闭浏览器,再次请求页面又得重新注册 Session。那么怎么传递 Session ID 呢?通过 URL 或者通过隐藏表单来传递,PHP 会自动将
[color="#3399cc"]session
ID 发送到 URL 上,URL 形如:http://www.openphp.cn/index.php?PHPSESSID=bba5b2a240a77e5b44cfa01d49cf9669,其中 URL 中的参数
[color="#3399cc"]PHP
SESSID 就是 Session ID了,我们可以使用 $_GET 来获取该值,从而实现
[color="#3399cc"]session
ID 页面间传递。
c}e3C Z}_31737
[$TW-H"^3F31737
<?
[color="#3399cc"]PHP
qB9w;~2Aaq31737
VwpI$D-y8vp31737// 保存一天 PHPChina 开源社区门户{ MM'p f;M
$lifeTime = 24 * 3600;PHPChina 开源社区门户|2zVb#FX3?g]
// 取得当前
[color="#3399cc"]session
名,默认为
[color="#3399cc"]PHP
SESSID PHPChina 开源社区门户{SJ/t&~CU }\
$sessionName =
[color="#3399cc"]session
_name();
#Cy` rT^d;Ae31737// 取得
[color="#3399cc"]session
ID
Hs'}#T+Nd(T,Q5Q [31737$sessionID = $_GET[$
[color="#3399cc"]session
Name]; PHPChina 开源社区门户 N;Mo6U&||1_
// 使用 session_id() 设置获得的
[color="#3399cc"]session
ID PHPChina 开源社区门户D(`~L a
session_id($
[color="#3399cc"]session
ID); PHPChina 开源社区门户w6f({:VZ-j zj w$q!es
PHPChina 开源社区门户3ZLn7dny0{
[color="#3399cc"]session
_set_cookie_params($lifeTime); PHPChina 开源社区门户0fg4XnjoP*?
[color="#3399cc"]session
_start();PHPChina 开源社区门户#?h[z ^e Baq
$_
[color="#3399cc"]session
["admin"] = true;PHPChina 开源社区门户7d;A,bX:k CJj6|1j
?>
PHPChina 开源社区门户3wlvw wf+CB6[i
对于虚拟主机来说,如果所有用户的 Session 都保存在系统临时文件夹里,将给维护造成困难,而且降低了安全性,我们可以手动设置 Session 文件的保存路径,session_save_path()就提供了这样一个功能。我们可以将
[color="#3399cc"]session
存放目录指向一个不能通过 Web 方式访问的文件夹,当然,该文件夹必须具备可读写
[color="#3399cc"]属性
。PHPChina 开源社区门户%k |7U@6g K Y6B
&jf:}#Q[Z*UPs8l&sH31737
<?
[color="#3399cc"]PHP
PHPChina 开源社区门户TC0y@T)e
// 设置一个存放目录
p%w2TB1y-a O ^31737$savePath = "./
[color="#3399cc"]session
_save_dir/"; PHPChina 开源社区门户Hq)E#yE9Vs&| q'zV
// 保存一天 PHPChina 开源社区门户#T$Ug:Q|;VIB
$lifeTime = 24 * 3600; PHPChina 开源社区门户Z8fu7[$N `Z5K9P
[color="#3399cc"]session
_save_path($savePath);
)f*r$KA"p#yx"tIt31737
[color="#3399cc"]session
_set_cookie_params($lifeTime);
4A6k5@T2o7j F _&^%@%` d31737
[color="#3399cc"]session
_start();
U2Q M;J.@([z4y31737$_
[color="#3399cc"]session
["admin"] = true;
4h{/i5Doe}n9gi_ |-n$q31737?>
PHPChina 开源社区门户^j3R/F%_;Gj:eV H
同 session_set_cookie_params(); 函数一样,session_save_path()
[color="#3399cc"]函数
也必须在
[color="#3399cc"]session
_start()
[color="#3399cc"]函数
调用之前调用。
M.f't8Ul[ \ q31737
`W8JI/S)g31737 我们还可以将数组,
[url=javascript:;][color="#009999"]对象[/url]
存储在
[color="#3399cc"]session
中。操作数组和操作一般变量没有什么区别,而保存对象的话,
[color="#3399cc"]PHP
会自动对对象进行序列化(也叫串行化),然后保存于
[color="#3399cc"]session
中。下面例子说明了这一点:
^,K)?*m {*E9s3e f31737
`2];ZMl31737
<?
[color="#3399cc"]PHP
/j|3} W E @31737class person PHPChina 开源社区门户!B8[ q,}~k$|1n*U2{7A [ E`
{
NK5c(]%]3X31737var $age; PHPChina 开源社区门户b3e&o1W3H o'Yxt:}4j Z)S
function output() { PHPChina 开源社区门户Bb0[&S(tI
echo $this->age;
#@'{0lc'Cz31737} PHPChina 开源社区门户X _?WF(hk7o
PHPChina 开源社区门户2K?5A D Mv#x5z
function setAge($age) { PHPChina 开源社区门户9S5Z$oEu[7@3?S
$this->age = $age; PHPChina 开源社区门户d0E/[ b H;R
}
R$g| Q&E)|z31737} PHPChina 开源社区门户'i R`S"|
?>PHPChina 开源社区门户%f.Vdr;e D9c Z%|
setage.
[color="#3399cc"]PHP
PHPChina 开源社区门户:m-]S7h&K9d
<?
[color="#3399cc"]PHP
PHPChina 开源社区门户9\;C2d c6? B5N]
[color="#3399cc"]session
_start(); PHPChina 开源社区门户 QHB}aWi4L
require_once "person.
[color="#3399cc"]PHP
"; PHPChina 开源社区门户9zmsl ~)C r
$person = new person(); PHPChina 开源社区门户 Y,V \"{6BUUL*x$x
$person->setAge(21);
-QA*V7K[V C-qu31737$_
[color="#3399cc"]session
['person'] = $person;
bQ5aeCQ31737echo "<a href='output'>check here to output age</a>";
:Yc9~+W$s)cxb31737?>PHPChina 开源社区门户!VCQ,Q~U{~ l^kP$?
output.
[color="#3399cc"]PHP
m:h FI&r})n31737<?
/[(br`9J4b3K!B31737// 设置回调
[color="#3399cc"]函数
,确保重新构建对象。
Z/\8PR+e31737ini_set('unserialize_callback_func', 'mycallback'); PHPChina 开源社区门户 l'D7m9}|Y
function mycallback($classname) { PHPChina 开源社区门户 _&Uu&H0H$c'm0u+UG
$classname . ".
[color="#3399cc"]PHP
"; PHPChina 开源社区门户"Z9A&D.mS6^]3ev
}PHPChina 开源社区门户p0R x*v#dn&T$u
[color="#3399cc"]session
_start();PHPChina 开源社区门户UOr2K A3N
$person = $_
[color="#3399cc"]session
["person"];
6RCCD$wt uP-P31737// 输出 21 PHPChina 开源社区门户k|'X(`mo
$person->output();
g eh"yuy31737?>
PHPChina 开源社区门户[~z9|]yiy5f+b D t
当我们执行 setage.php 文件的时候,调用了 setage() 方法,设置了年龄为 21,并将该状态序列化后保存在
[color="#3399cc"]session
中(PHP 将自动完成这一转换),当转到 output.php 后,要输出这个值,就必须反序列化刚才保存的对象,又因为在解序列化的时候需要实例化一个未定义类,所以我们定义了以后回调
[color="#3399cc"]函数
,自动包含 person.
[color="#3399cc"]PHP
这个类文件,因此对象被重构,并取得当前 age 的值为 21,然后调用 output() 方法输出该值。PHPChina 开源社区门户?$Bw zc
'm IE2MM31737 另外,我们还可以使用 session_set_save_handler
[color="#3399cc"]函数
来自定义
[color="#3399cc"]session
的调用方式。
相关阅读 更多 +