优雅地使用CodeIgniter 3之Session类库(1)(转)
相信无数人在使用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)(转)的更多相关文章
- CodeIgniter 3之Session类库(3)(转)
本文主要讲CI2和CI3关于Session类库的区别.我们知道CI2的Session类使用了cookie来传递session数据.使用 cookie保存会话的好处在于可以节省服务器资源,但坏处也是显而 ...
- CodeIgniter 3之Session类库(2)(转)
CI3的Session的重大改变就是默认使用了原生的Session,这符合Session类库本来的意思,似乎更加合理一些.总体来说,虽然设计理念不同,但为了保证向后兼容性,类库的使用方法与CI2.0的 ...
- CodeIgniter配置之SESSION
刚使用Codeigniter时也被其中的SESSION迷惑过,后来就再也没用过CI自带的SESSION,想必还是有必要整理一下SESSION.为弄清CI中的SESSION,先来说一下PHP中SESSI ...
- CodeIgniter中的session处理
在CI中你可以这样很简单地装载library: $this->load->library('newclass'); 注意系统中会有两个library目录,一个是system/ ...
- CodeIgniter类库之Benchmarking Class ,计算代码的执行时间
CodeIgniter中有个Benchmarking类库,它是被系统自动被加载的,不需要手工加载.Benchmarking类库能够计算出任意两个被标记点之间的代码执行时间.通过这个数值,可以评估程序员 ...
- ***CodeIgniter集成微信支付(转)
微信支付Native扫码支付模式二之CodeIgniter集成篇 http://www.cnblogs.com/24la/p/wxpay-native-qrcode-codeigniter.html ...
- 微信支付JSAPI模式及退款CodeIgniter集成篇
微信支付接口文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_1 首先你得知道这个jsapi是不能离开微信进行调用支付的,明白 ...
- CI框架SESSION重写
这个是我平时用的是 PHP 自己的 Session 机制,是真正的 PHP Session,存储在服务器端,而不是用的 cookie 接口完全兼容于 CI 2.0.x 的 Session 类库,也就是 ...
- CodeIgniter配置之config
配置说明 $config['language']:指定项目语言包.需要注意的时Codeigniter自带的类库错误提示语言包位于/system/language/english/目录下,当这里配置非e ...
随机推荐
- Android 4.4KitKat AudioRecord 流程分析
Android是架构分为三层: 底层 Linux Kernel 中间层 主要由C++实现 (Android 60%源码都是C++实现) 应用层 主要由JAVA开发的应用程序 应用程序执行 ...
- MongoDB 安装,启动与基本使用
一.MongoDB简介 MongoDB是一个高性能,开源,无模式的文档型数据库,是当前NoSql数据库中比较热门的一种.它在许多场景下可用于替代传统的关系型数据库或键/值存储方式.Mongo使用C++ ...
- linux下tomcat下部署项目如何打包压缩备份
范例一:将整个 /etc 目录下的文件全部打包成为 /tmp/etc.tar[root@linux ~]# tar -cvf /tmp/etc.tar /etc <==仅打包,不压缩![root ...
- JavaWeb项目开发案例精粹-第6章报价管理系统-06po层
1. <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www ...
- Java科普之算法剖析
本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处! 从小白晋升,一路走来:从helloworld,到JFrame,再到Android:从城外小子,到内城 ...
- Qt通过UDP传图片,实现自定义分包和组包
一.包头结构体 //包头 struct PackageHeader { //包头大小(sizeof(PackageHeader)) unsigned int uTransPackageHdrSize; ...
- .NET 压缩解压库发布,支持进度查看
刚发布了一个 .net压缩解压库,基于SharpZipLib开发 ,支持进度查看,支持路径保持与否. CL.IO.Zip 是一个基于SharpZipLib的一个压缩和解压的类库,提供给用户在.net环 ...
- 《Java编程那点事儿》读书笔记(七)——多线程
1.继承Thread类 通过编写新的类继承Thread类可以实现多线程,其中线程的代码必须书写在run方法内部或者在run方法内部进行调用. public class NewThread extend ...
- datetimepicker文件
很有诚意先放下载地址百度网盘 最近在做angular的项目,找一个合适的 datepicker ,首选bootstrap-datetimepicker,但是项目中没有到bootstrap, 整理处理下 ...
- MongoDB安装Windows服务
由于官方下载较慢.这里提供一个个人百度共享网盘地址: http://pan.baidu.com/s/1mhHW0nI mongodb-win32-x86_64-3.2.3 使用以下命令将MongoDB ...