相信无数人在使用CI2的Session类库时,遇到各种的坑,各种抱怨,各种不解。在CI中国论坛能搜到大量关于Session类库的提问,说明要想用 好session类库还是得下一番功夫。本文将先从CI2入手,讲述CI下Session类库的设计理念和在CI3下的Session类库做了哪些重大改 进。首先在这里简单说明一下Session和cookie的区别。

Session和cookie的区别

1.在某些语境中,cookie是session的一种实现方式,Ci的类库设计似乎就这么认为的。设想用户登录后使用Session保存数据的一种情 景。用户输入密码和口令发送到服务器后,php就会在服务器端生成一个php sessionid和一个具体的数据包放到一个文件中,并存放到指定的文件夹下(如果session.save_handler=files),然后会把 sessionId作为一个cookie放到响应中返回给客户端(前提是用户浏览器开启了cookie,否则会加入到url地址的查询字符串中)。用户再 次访问服务器上的其他页面时,会把这个phpsessionid的cookie携带上作为请求的一部分发送给服务器,服务器就能根据session id到保存session的文件夹下找到特定的文件,读取其中的数据。

2.而cookie,在服务器端和客户端都是可以设置的。在客户端设置(通过js)时,主要作用是用户在自己的浏览器页面跳转时能传递数据。服务端不会太
多理睬客户端设置的cookie,客户端发过来什么,它就原封不动地返回什么。同时,服务器也会发出让客户端设置cookie的指令,下次请求时客户端也
会无脑地把cookie发送到服务器。

在CI2.0版本的Session类库中,默认使用了cookie来保存session,便带给我们各种不解。下面谈下CI2.0的session工作原理。

基本原理

使用Session库时,会有一个元数据。我们可以把这个元数据理解为在浏览器和服务器之间的一个令牌,有了这个令牌,服务器的城门才会对客户端的请求敞
开。客户端好比是一个信使,要去服务器的王宫里报告信息,服务器的门卫就会检查这个令牌,这个令牌包含的基本信息是:ip地址、user
agent、上次活动时间、Session id,其中Session id是重要的,Session id不对,直接拒绝。但是门卫也可能根据上级指示,需要根据他的外表判断是否是来自特定地区(IP地址的限制)、看下他的服饰是否符合某些特征(user agent限制),是否令牌是否已经过期(上次活动时间),如果都满足才能让特定的西域人进入王宫。

1 Array
2 (
3     [session_id] => 4a5a5dca22728fb0a84364eeb405b601
4     [ip_address] => 127.0.0.1
5     [user_agent] => Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_7;
6     [last_activity] => 1303142623
7 )

门卫得到的上级指示来自于配置文件,它们放在config.php中:

1 $config['sess_match_ip']  = FALSE;
2 $config['sess_match_useragent'] = TRUE;
3 $config['sess_time_to_update'] = 300;

门卫会拿令牌里的信息(http请求携带的cookie)和真实的信息(http请求头的信息)比对,判断你是否是合法的,不合法的话,就会认为你来路不
明,拒绝你携带来的任何数据信息。如果你在使用CI自带的Session库时,总是出现读不到数据的情况,你就要看下你是否要求门卫检查的过于严格。特别
是当设置sess_match_useragent设为TRUE时,会遇到各种的坑:

1. 你用flash组件上传文件,只有登录的用户才能上传文件,结果你每次判断用户是否登录都会出错,因为flash发送的http请求有可能更改了user agent;

2. 使用ie切换不同的模式,比如兼容模式,也会造成user agent不同;

3. user agent的长度最长是120个字符,手动设置User agent是需要截取字符到最大120个。

4. 另外,如果出现“Cannot modify header information - headers already sent by”错误,基本可以断定是你文件的编码格式有误,请去掉bom头。

安全问题

CI使用cookie来传递数据本来就不够安全,而且如果数据量巨大时也会有性能问题。但是CI还是友好地加入以下几个安全验证机制:

1. 加密令牌

1 $config['encryption_key'] = 'mahuaz_';
2 $config['sess_encrypt_cookie'] =  TRUE;

设置后,客户端检查cookie时就可以看到加密后的序列化数据。

2. 自动更新机制

CI
默认每五分钟更新一次令牌,更新发生在客户端的一次请求中。客户端每发送一次请求,会把cookie的信息发送到服务器,服务器根据发来的cookie判
断是否到了应该更换令牌的时间了,如果是,就会重新换一个新的令牌返回给客户端。这就相当于门卫给你换了令牌,下次要使用新令牌进门。此时即使有坏人伪造
了一个令牌也不起作用了,因为旧令牌已经作废。这样就相当于加了一条安全机制。可以使用:

1 $config['sess_time_to_update'] = 300;

来设置多长时间来换一次令牌。这个时间不要设置的太短,更新频繁也会影响性能。这里不要和sess_expiration混淆:

1 $config['sess_expiration']  = 7200;

这个配置是用来指示整个cookie的过期时间的,相当于令牌完全失效,再怎么更换都不起作用。

在CI中文论坛上,每每有遇到各种session问题,总有人推荐使用hex封装的Session库 ,或者使用stblog的作者Saturn的Session库https://github.com/cnsaturn/codeigniter-my-session前者使用PHP原生Session,不需要额外配置;后者需要安装 memcached 服务以及 memcache/memcached 扩展。hex封装的这个Session库特性有限,它有如下特点:

1. 简化了CI自带Session的安全机制,没有做每五分钟更新session_id的设置;

2.没有加密Session;

3.永远不会过期,虽然它会读取$config['sess_expiration'] =
7200;判断Session是否过期,但是如果发现过期的话,并不是直接返回空数据,而是重新产生一个新的Session
id,把旧数据转到新数据中。除非你超过了最大gc回收时间:7200s。

4.config.php中的以下配置节都没任何用处:

1 $config['sess_cookie_name']  = 'ci_session';
2 //$config['sess_expiration']  = 7200; 该配置节有用
3 $config['sess_expire_on_close'] = FALSE;
4 $config['sess_encrypt_cookie'] = FALSE;
5 $config['sess_use_database'] = FALSE;
6 $config['sess_table_name']  = 'ci_sessions';
7 $config['sess_match_ip']  = FALSE;
8 $config['sess_match_useragent'] = TRUE;
9 $config['sess_time_to_update'] = 300;

所以,使用这个库也只能解决大部分问题,真正的解决方案也只能等到CI3来处理,事实上CI3也如愿地解决了上面提到的很多问题。下一节我们讲讲如何使用CI3的session。

http://www.ifixedbug.com/posts/how-to-use-codeigniter3-session-1

优雅地使用CodeIgniter 3之Session类库(1)(转)的更多相关文章

  1. CodeIgniter 3之Session类库(3)(转)

    本文主要讲CI2和CI3关于Session类库的区别.我们知道CI2的Session类使用了cookie来传递session数据.使用 cookie保存会话的好处在于可以节省服务器资源,但坏处也是显而 ...

  2. CodeIgniter 3之Session类库(2)(转)

    CI3的Session的重大改变就是默认使用了原生的Session,这符合Session类库本来的意思,似乎更加合理一些.总体来说,虽然设计理念不同,但为了保证向后兼容性,类库的使用方法与CI2.0的 ...

  3. CodeIgniter配置之SESSION

    刚使用Codeigniter时也被其中的SESSION迷惑过,后来就再也没用过CI自带的SESSION,想必还是有必要整理一下SESSION.为弄清CI中的SESSION,先来说一下PHP中SESSI ...

  4. CodeIgniter中的session处理

    在CI中你可以这样很简单地装载library:     $this->load->library('newclass');    注意系统中会有两个library目录,一个是system/ ...

  5. CodeIgniter类库之Benchmarking Class ,计算代码的执行时间

    CodeIgniter中有个Benchmarking类库,它是被系统自动被加载的,不需要手工加载.Benchmarking类库能够计算出任意两个被标记点之间的代码执行时间.通过这个数值,可以评估程序员 ...

  6. ***CodeIgniter集成微信支付(转)

    微信支付Native扫码支付模式二之CodeIgniter集成篇  http://www.cnblogs.com/24la/p/wxpay-native-qrcode-codeigniter.html ...

  7. 微信支付JSAPI模式及退款CodeIgniter集成篇

    微信支付接口文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_1 首先你得知道这个jsapi是不能离开微信进行调用支付的,明白 ...

  8. CI框架SESSION重写

    这个是我平时用的是 PHP 自己的 Session 机制,是真正的 PHP Session,存储在服务器端,而不是用的 cookie 接口完全兼容于 CI 2.0.x 的 Session 类库,也就是 ...

  9. CodeIgniter配置之config

    配置说明 $config['language']:指定项目语言包.需要注意的时Codeigniter自带的类库错误提示语言包位于/system/language/english/目录下,当这里配置非e ...

随机推荐

  1. POJ 1953

    //FINBONACI数列 #include <iostream> #define MAXN 100 using namespace std; int _m[MAXN]; int main ...

  2. JAVA动态加载JAR包的实现

    如何动态的加载这些驱动!不可能把所有的数据库驱动都集成到JAR包中吧?!于是动态加载驱动的JAR包就产生了!其实这些在做系统基础代码时,经常用到,只是一般我们没有机会去搞而已. 动态加载JAR包,使用 ...

  3. ZOJ 2588 Burning Bridges (tarjan求割边)

    题目链接 题意 : N个点M条边,允许有重边,让你求出割边的数目以及每条割边的编号(编号是输入顺序从1到M). 思路 :tarjan求割边,对于除重边以为中生成树的边(u,v),若满足dfn[u] & ...

  4. centOS学习part3:远程工具VNC的安装与配置

    0 上一篇(http://www.cnblogs.com/souvenir/p/3875484.html)我们介绍了通过yum安装JDK的实例,初步见识了yum命令的强大.本章我们将继续使用yum命令 ...

  5. 五分钟轻松搞定产品需求文档!这可能史上最全PRD文档模板

    本文由  @JustWu 原创发布于社区 为什么写这篇文章? 第一:写PMCAFF的PRD文档,大家都是用户,比较好参考与理解,方便大家来找我写的不好的地方. 第二:我在自学PRD文档的编写过程中,总 ...

  6. java--vo

    VO是跟数据库里表的映射,一个表对应一个VO DAO是用VO来访问真实的表,对数据库的操作都在DAO中完成 BO是业务层,做逻辑处理的 VO , PO , BO , QO, DAO ,POJO, O/ ...

  7. HTML5之拖拽(兼容IE和非IE)

    前世:项目中需要拖动div,然后和某个div进行位置交换,这不是关键,关键是还要保存位置,然后在下次打开的时候按照保存的位置显示.还好本人功力深厚,一下子就想到了用localStorage来保存,事实 ...

  8. 《mysql数据库备份小脚本》(转)

    vim mysql.sh #!/bin/bashDAY=`date +%Y-%m-%d` //日期以年月日显示并赋予DAY变量SIZE=`du -sh /var/lib/mysql //查看mysql ...

  9. Residual Networks <2015 ICCV, ImageNet 图像分类Top1>

    本文介绍一下2015 ImageNet中分类任务的冠军——MSRA何凯明团队的Residual Networks.实际上,MSRA是今年Imagenet的大赢家,不单在分类任务,MSRA还用resid ...

  10. C# 数组、一维数组、二维数组、多维数组、锯齿数组

    C#  数组.一维数组.二维数组.多维数组.锯齿数组 一.数组: 如果需要使用同一类型的对象,就可以使用数组,数组是一种数据结构,它可以包含同一类型的多个元素.它的长度是固定的,如长度未知的情况下,请 ...