1、基础知识
1.1、概念
session是服务器保持会话数据的一种方法,对应cookie是在客户端保持用户数据。
1.2、出现理由
HTTP协议的无状态
1.3、PHP的Session设计构造
Session分以下几部分:
1)Session id
用户Session的唯一标识(随机生成,具有唯一性,随机性)
2)Session data
保存用户状态信息(用户数据)
3)Session file
Session的存储方式,文件存储方式以"sess_"前缀+"Session_id"后缀的方式存储
格式如下:
1
|
sess_d3eom13a9r9p5i5nj923voqaf7
|
4)Session lifetime
Session生存时间(从Session的产生到生命周期的结束)
1.4、工作原理
1)客户端与服务器建立联系
2)客户端将session id传递给服务器
3)服务器根据session id建立相应的session id文件(session id序列化保存,读取时反序列化)
唯一标识的方法有两种:cookie或者通过GET方式指定
1.5、Session的缺点
1)使用Session会影响系统性能(受文件系统设计影响,目录定义超过10000个文件非常耗时)
2)Session文件大小1~2K,数量庞大的小文件影响硬盘IO性能
1.6、Session配置文件
1.6.1、默认配置文件的路径
1
|
/etc/php
.ini
|
1.6.2、查找配置文件
1
|
find
/ -name php.ini
|
显示如下:
1
|
/etc/php
.ini
|
1.6.3、配置文件的参数
vim编辑/etc/php.ini
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
[Session]
session.save_handler = files
#session的存储方式
session.use_cookies= 1
#使用cookies在客户端保存会话
session.use_only_cookies = 1
#去保护URL中传送session id的用户
session.name = PHPSESSID
#session名称(默认PHPSESSID)
session.auto_start = 0
#不启用请求自动初始化session
session.cookie_lifetime = 0
#cookie存活时间(0为直至浏览器重启,单位秒)
session.cookie_path = /
#cookie的有效路径
session.cookie_domain =
#cookie的有效域名
session.cookie_httponly =
#httponly标记增加到cookie上(脚本语言无法抓取)
session.serialize_handler = php
#PHP标准序列化
session.gc_probability =1
session.gc_divisor =1000
#建议设置1000-5000
#概率=session.gc_probability/session.gc_divisor(1/1000)
#页面访问越频繁概率越小
session.gc_maxlifetime =1440
#过期时间(默认24分钟,单位秒)
session.bug_compat_42 = off
#全局初始化session变量
session.bug_compat_warn = off
session.referer_check =
#防止带有ID的外部URL
session.entopy_length = 0
#读取的字节
session.cache_limiter = {nocache,private,pblic}
#HTTP缓冲类型
session.cache_expire = 180
#文档过期时间(分钟)
session.use_trans_sid = 1
#trans_sid支持(默认0)
session.hash_function = 0
#hash方法{0:md5(128 bits),1:SHA-1(160 bits)}
session.hash_bits_per_character = 5
#当转换二进制hash数据奥可读形式是,每个字符保留位数
session.save_path =
"/var/lib/php/session"
#session id存放路径
|
1.6.4、session的保存目录
1)默认路径:
1
|
ls
-l
/var/lib/php/session
|
显示如下:
1
2
3
4
5
6
7
8
|
total 20
-rw-------. 1 apache apache 31 Jan 13 08:41 sess_0bl5a7anlurcguu1t8qbmjkus5
-rw-------. 1 apache apache 1320 Nov 24 16:40 sess_brv2cvkbhiqehpqu7tgabuvo81
-rw-------. 1 apache apache 31 Jan 13 08:39 sess_d3eom13a9r9p5i5nj923voqaf7
-rw-------. 1 apache apache 31 Jan 13 08:47 sess_j04uc0jaia0sr4qjdrull99hh0
-rw-------. 1 apache apache 31 Jan 13 07:03 sess_me2vo12m5vnlpk1s0oj60mgqv1
-rw-------. 1 apache apache 0 Jan 13 08:41 sess_s4q1ivktojrm8ruv54ob12tol1
-rw-------. 1 apache apache 0 Jan 13 08:41 sess_u3mcdh4cs329131eo6tk7hts22
|
2)路径查找方法:
1
|
find
/ -name session
|
显示如下:
1
|
/var/lib/php/session
|
3)配置文件自定路径
1
|
grep
session.save_path
/etc/php
.ini
|
会发现如下行:
1
|
session.save_path =
"/var/lib/php/session"
|
注:session.save_path定义的路径需手动创建并赋予apache用户读写权限。
4)分层子目录定义
1
|
session.save_path =
"N;[MODE;]/path"
|
注:
-- N定义目录层数(例如2,目录需手动创建)
-- MODE定义单目录最大会话文件数量(默认8进制600)
5)分层子目录的生成脚本
源代码tar包含名称为“mod_files.sh”的分层子目录生成脚本,代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
#!/usr/bin/env bash
if
[[
"$2"
=
""
]] || [[
"$3"
=
""
]];
then
echo
"Usage: $0 BASE_DIRECTORY DEPTH HASH_BITS"
echo
"BASE_DIRECTORY will be created if it doesn't exist"
echo
"DEPTH must be an integer number >0"
echo
"HASH_BITS(session.hash_bits_per_charactor) should be one of 4, 5, or 6"
exit
1
fi
if
[[
"$2"
=
"0"
]] && [[ !
"$4"
=
"recurse"
]];
then
echo
"Can't create a directory tree with depth of 0, exiting."
fi
if
[[
"$2"
=
"0"
]];
then
exit
0
fi
directory=
"$1"
depth=
"$2"
hashbits=
"$3"
hash_chars=
"0 1 2 3 4 5 6 7 8 9 a b c d e f"
if
[[
"$hashbits"
-
ge
"5"
]];
then
hash_chars=
"$hash_chars g h i j k l m n o p q r s t u v"
fi
if
[[
"$hashbits"
-
ge
"6"
]];
then
hash_chars=
"$hash_chars w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z - ,"
fi
while
[[ -d $directory ]] && [[ $(
ls
$directory ) ]];
do
echo
"Directory $directory is not empty! What would you like to do?"
options=
"\"Delete directory contents\" \"Choose another directory\" \"Quit\""
eval
set
$options
select
opt
in
"$@"
;
do
if
[[ $opt =
"Delete directory contents"
]];
then
echo
"Deleting $directory contents... "
rm
-rf $directory/*
elif
[[ $opt =
"Choose another directory"
]];
then
echo
"Which directory would you like to choose?"
read
directory
elif
[[ $opt =
"Quit"
]];
then
exit
0
fi
break
;
done
done
if
[[ ! -d $directory ]];
then
mkdir
-p $directory
fi
echo
"Creating session path in $directory with a depth of $depth for session.hash_bits_per_character = $hashbits"
for
i
in
$hash_chars;
do
newpath=
"$directory/$i"
mkdir
$newpath ||
exit
1
bash
$0 $newpath `
expr
$depth - 1` $hashbits recurse
done
|
使用格式如下:
1
2
3
4
|
bash
mod_files.sh <directory> <depth> <hashbits>
directory -- Session目录存放的根目录
depth -- 目录的深度
hashbits -- 哈希值(散列值)
|
使用范例(N=2):
1
|
bash
mod_files.sh
/var/lib/php/session
2 5
|
生成的目录名称大致如下:
-- 有传参下子目录名称一般以16进制"0 1 2 3 4 5 6 7 8 9 a b c d e f"字母命名
-- 传参设置hashbits=5 以上加字母"g h i j k l m n o p q r s t u v"
-- 传参设置hashbits=6 以上加字母"w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z - ,"
1.6.5、session的保存方式
1)文件方式保存
1
|
session.save_handler = files
|
2)处理器方式(如mysql)
1
|
session.save_handler = user
|
1.6.6、开启客户端会话保存
1
|
session.use_cookies = 1
|
1.7、Session的同步
场景:应用程序层有多台服务器,服务器之间做负载均衡,可通过如下方式解决:
1)Session存储于数据库
2)存储于共享存储(NFS)
3)负载均衡器保持会话
1.8、Session的管理脚本
删除24分钟内没有被改变的Session文件
1
|
cd
/var/lib/php/session
;
find
-cmin +24 |
xargs
rm
|
1.9、内存直存Session的方法
内存直接存储Session可以改善Session存储的性能(重启丢失),设置方法如下:
vim编辑/etc/php.ini
修改如下参数
1
|
session.save_path =
"/dev/shm"
|
注:"/dev/shm"相当于内存入口
2、实践部分
2.1、基础环境配置
请参阅如下文档配置PHP环境:
http://cmdschool.blog.51cto.com/2420395/1708325
2.2、yum源安装
1
|
yum -y
install
wget tree
|
2.3、配置部分
2.3.1、step1
官方下载源安装包
1
2
|
cd
~
wget http:
//cn2
.php.net
/distributions/php-7
.0.2.
tar
.bz2
|
2.3.2、step2
解压源码包
1
|
tar
-xf php-7.0.2.
tar
.bz2
|
2.3.3、step3
执行设置脚本
1
2
3
4
|
cd
php-7.0.2
/ext/session
bash
mod_files.sh
/var/lib/php/session/
2 5
chown
-R apache:apache
/var/lib/php/session/
chmod
700 -R
/var/lib/php/session/
|
2.3.4、step4
检查目录结构
1
|
tree
/var/lib/php/session/
|
显示如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
/var/lib/php/session/
├── 0
│ ├── 0
│ ├── 1
│ ├── 2
│ ├── 3
│ ├── 4
│ ├── 5
│ ├── 6
│ ├── 7
│ ├── 8
│ ├── 9
│ ├── a
│ ├── b
│ ├── c
│ ├── d
│ ├── e
│ ├── f
│ ├── g
│ ├── h
│ ├── i
│ ├── j
│ ├── k
│ ├── l
│ ├── m
│ ├── n
│ ├── o
│ ├── p
│ ├── q
│ ├── r
│ ├── s
│ ├── t
│ ├── u
│ └──
v
├── 1
│ ├── 0
│ ├── 1
│ ├── 2
#中间有节删
1056 directories, 0 files
|
2.3.5、step5
检查目录权限
1
|
ls
-l
/var/lib/php/session/
|
2.3.6、step6
重启httpd服务使PHP的Session相关设置生效
1
|
/etc/init
.d
/httpd
restart
|
2.3.7、step7
增加测试代码:
vim编辑/var/www/www.cmdschool.org/test.php
创建如下代码:
1
2
3
4
5
6
|
<?php
session_start();
$_SESSION[
"user_name"
]=
"cmdschool.org"
;
echo
$_SESSION[
"user_name"
];
echo
" <a href=\"test2.php\">test2</a>"
?>
|
vim编辑/var/www/www.cmdschool.org/test2.php
创建如下代码:
1
2
3
4
|
<?php
session_start();
echo
$_SESSION[
"user_name"
];
?>
|
2.3.8、step8
模拟DNS解析:
1
|
notepad %SystemRoot%\System32\drivers\etc\hosts
|
建立如下映射:
1
|
10.168.0.170 www.cmdschool.org
|
2.3.9、step9
测试与检查:
1)浏览器测试
http://www.cmdschool.org/test.php
如上图所示:
本页生成Session变量"user_name"并赋值"cmdschool.org"
单击【test2】跳转页面
如上图所示:
本页输出Session变量"user_name"的值"cmdschool.org"
2)日志检查
1
|
tail
/var/log/httpd/error_log
|
3)检查生成的Session文件
1
|
tree
/var/lib/php/session
|
显示如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
#前有节删
├── n
│ ├── 0
│ ├── 1
│ ├── 2
│ ├── 3
│ ├── 4
│ ├── 5
│ ├── 6
│ ├── 7
│ ├── 8
│ ├── 9
│ ├── a
│ ├── b
│ ├── c
│ ├── d
│ ├── e
│ ├── f
│ ├── g
│ ├── h
│ ├── i
│ ├── j
│ ├── k
│ ├── l
│ ├── m
│ ├── n
│ ├── o
│ │ └── sess_no8luf5jctfd2igrqikpc6mji2
#后有节删
|
文件查阅
1
|
cat
/var/lib/php/session/n/o/sess_no8luf5jctfd2igrqikpc6mji2
|
显示如下:
1
|
user_name|s:13:
"cmdschool.org"
;
|
---------------------------------------------------------------------