Cookie和Session有一些不同:
- 存储位置的不同:Cookie将状态保存在客户端,Session将状态保存在服务器端;
- 与HTTP协议的关系不同:Cookie需要通过网络传输,依赖于HTTP协议,Session并没有在HTTP的协议中定 义;
- 可用性不同:相对于Cookie,Session在客户端禁用Cookie后还可以通过URL回写机制实现Session会话机制。
- 安全性不同:因为存储的位置不同,Cookie更容易被篡改,存储在服务器的Session相对来说则安全一些,客户不能随意读取这些内容,除非获到其它用户的了sessionID,这也是XSS攻击会关注的地方。
-
同源策略,说到WEB的安全问题就不得不提同源策略。浏览器的同源策略是 Web 安全的基础,所有的主流浏览器都会有相应的实现。同源策略中“源”是一个包含主机名、协议和端口号的三元组,则同源表示:同协议,同域名和同端口,三者都 相同。同源策略的出发点是它认为自任何站点装载的信赖内容是不安全的。在同源策略的限制下,浏览器只允许网页中的脚本(如 JavaScript 或 VBScript)访问与之同源的 HTTP 请求和 Cookie。对于Cookie来说,同源策略就限制了网站间的Cookie读写操作。即使在服务器使用setcookie(PHP)函数对其它域名执行 Cookie写操作也是无效的。 setcookie的域名是用来指向当前域名或根域名之类的用的,设置Cookie时,如果不指定domain的值,默认就是本域。
; http://php.net/session.save-path
;session.save_path = "/tmp" ://tcp:localhost:1121,.... ; Whether to use cookies. ; http://php.net/session.use-cookies session.use_cookies = 1 ; http://php.net/session.cookie-secure ;session.cookie_secure = ; This option forces PHP to fetch and use a cookie for storing and maintaining ; the session id. We encourage this operation as it's very helpful in combating ; session hijacking when not specifying and managing your own session id. It is ; not the end all be all of session hijacking defense, but it's a good start. ; http://php.net/session.use-only-cookies session.use_only_cookies = 1 ; Name of the session (used as cookie name). ; http://php.net/session.namesession.name = PHPSESSIDsession 服务端
sessionid
- //生成所需的session id,当然后面还需要后续的处理~
- //格式为:%.15s%ld%ld%0.8F,每一段的含义如下:
- //%.15s remote_addr ? remote_addr : "" 这一行很容易理解
- //%ld tv.tv_sec 当前的时间戳
- //%ld (long int)tv.tv_usec 当前毫秒数
- //%0.8F php_combined_lcg(TSRMLS_C) * 10 一个随机数
客户端:
1:cookie
2:url
session_id($session_id);
如果 url中的传递session_id的key=session.name = PHPSESSID
就不用再强制指定session_id了
The constant SID can also be used to retrieve the current name and session id as a string suitable for adding to URLs
SID:开启cookie就用cookie ,不开启就使用url PHPSESSION=$session_id
; trans sid support is disabled by default.
; Use of trans sid may risk your users security. ; Use this option with caution. ; - User may send URL contains active session ID ; to other person via. email/irc/etc. ; - URL that contains active session ID may be stored ; in publicly accessible computer. ; - User may access your site with the same session ID ; always using URL stored in browser's history or bookmarks. ; http://php.net/session.use-trans-sidsession.use_trans_sid = 1会在: 页面调转、提交、时自动加上PHPSESSION
而php程序中的header调转需要手动加上SID
;就可以完成同时基于cookie和url
服务端:
删除session:
$_SESSION = array()
删除cookie:基于cookie的
setCookie(session_name(),time()-3600,'/');//php.ini下配置session.cookie_path=/ 根目录下
session_destory()//服务端的
/SESSION高级用法
一、介绍SESSIO信息写入到自己定义的位置
1. 解决跨机保存SESSION 在Linux下可以使用nfs或是samba, 共享文件夹的方式 使用数据库来实现 memcache来保存会话信息 session_set_save_handler() 2. 解决在线用户信息 二、介绍一下PHP配置文件中的常用选择(PHP.in) (写个例子演示, 以下参数,用默认的存储方未予) session.name ;使用cookie保存时 cookie中的名称 session.use_trans_sid;不使用cookie时自动将所用连接指定成 session_name 是否启用sid的支持 启用SID的支持 session.save_path= //基于cookie的session信息 session.use_cookies =1 session.cookie_path = '/' session.cookie_domain = '' session.cookie_lifetime = 0 session.save_handler= memcache(session.save_path=tcp://$ip:11211) session.gc_maxlifetime garbage collection 垃圾回收 指定过了多少秒之后数据就会被视为“垃圾”,并被清除 session.gc_probability=1 session.gc_divisor=100 这两个合起来就是启动gc进程管理概率的 初使化时(session_start()) session.gc_probability/session.gc_divisor 1/100 的概率启动gc 三、介绍一下session_set_save_handler()函数的使用 session_set_save_handler()//控制session的保存方式 session.save_handler = files;//user -----------------------方法如下--------------<?php
//在运行session_start(); //启动 function open($save_path, $session_name){ global $sess_save_path; $sess_save_path=$save_path; return true; } //session_write_close() session_destroy() function close(){ return true; } //session_start(), $_SESSION, 读取session数据到$_SESSION中 function read($id){ global $sess_save_path; $sess_file=$sess_save_path."/glf_".$id; return (string)@file_get_contents($sess_file); } //结束时和session_write_close()强制提交SESSION数据 $_SESSION[]="aaa"; function write($id, $sess_data){ global $sess_save_path; $sess_file=$sess_save_path."/glf_".$id; if($fp=@fopen($sess_file, "w")){ $return=fwrite($fp, $sess_data); fclose($fp); return $return; }else{ return false; } } //session_destroy() function destroy($id){ global $sess_save_path; $sess_file=$sess_save_path."/glf_".$id; return @unlink($sess_file); } //ession.gc_probability和session.gc_divisor值决定的,open(), read() session_start也会执行gc function gc($maxlifetime){ global $sess_save_path; foreach(glob($sess_save_path."/glf_*") as $filename){ if(filemtime($filename)+$maxlifetime < time() ){ @unlink($filename); echo $filename; } } return true; } session_set_save_handler("open", "close", "read", "write", "destroy","gc"); session_start(); 四、写入自己定义的文件,或远程服务器的硬盘中 五、将SESSION数据写入数据库中(使用PDO) session_set_save_handler(); pdo 1. 表设计 2. 用类编写完成,写入数据库的表中session 3. 加入到实例中 类中各回调函数定义都要定义为静态方法,属性也要是静态的(静态成员使用) SESSIONID, update_time, client_ip, data -----------------类方法---<?php
class Session { private static $handler=null; private static $ip=null; private static $lifetime=null; private static $time=null; private static function init($handler){ self::$handler=$handler; self::$ip = !empty($_SERVER["REMOTE_ADDR"]) ? $_SERVER["REMOTE_ADDR"] : 'unknown'; self::$lifetime=ini_get('session.gc_maxlifetime'); self::$time=time(); } static function start(PDO $pdo){ self::init($pdo); session_set_save_handler( array(__CLASS__,"open"), array(__CLASS__,"close"), array(__CLASS__,"read"), array(__CLASS__,"write"), array(__CLASS__,"destroy"), array(__CLASS__,"gc") ); session_start(); } public static function open($path, $name){ return true; } public static function close(){ return true; } public static function read($PHPSESSID){ $sql="select PHPSESSID, update_time, client_ip, data from session where PHPSESSID= ?"; $stmt=self::$handler->prepare($sql); $stmt->execute(array($PHPSESSID)); if(!$result=$stmt->fetch(PDO::FETCH_ASSOC)){ return ''; } if( self::$ip != $result["client_ip"]){ self::destroy($PHPSESSID); return ''; } if(($result["update_time"] + self::$lifetime) < self::$time ){ self::destroy($PHPSESSID); return ''; } return $result['data']; } public static function write($PHPSESSID, $data){ $sql="select PHPSESSID, update_time, client_ip, data from session where PHPSESSID= ?"; $stmt=self::$handler->prepare($sql); $stmt->execute(array($PHPSESSID)); if($result=$stmt->fetch(PDO::FETCH_ASSOC)){ if($result['data'] != $data || self::$time > ($result['update_time']+30)){ $sql="update session set update_time = ?, data =? where PHPSESSID = ?"; $stm=self::$handler->prepare($sql); $stm->execute(array(self::$time, $data, $PHPSESSID)); } }else{ if(!empty($data)){ $sql="insert into session(PHPSESSID, update_time, client_ip, data) values(?,?,?,?)"; $sth=self::$handler->prepare($sql); $sth->execute(array($PHPSESSID, self::$time, self::$ip, $data)); } } return true; } public static function destroy($PHPSESSID){ $sql="delete from session where PHPSESSID = ?"; $stmt=self::$handler->prepare($sql); $stmt->execute(array($PHPSESSID)); return true; } private static function gc($lifetime){ $sql = "delete from session where update_time < ?"; $stmt=self::$handler->prepare($sql); $stmt->execute(array(self::$time-$lifetime)); return true; } } try{ $pdo=new PDO("mysql:host=localhost;dbname=xsphpdb", "root", "123456"); }catch(PDOException $e){ echo $e->getMessage(); } Session::start($pdo); 六、将SESSION信息写入到MemCache服务器中<?php
class MemSession { private static $handler=null; private static $lifetime=null; private static $time = null; const NS='session_'; private static function init($handler){ self::$handler=$handler; self::$lifetime=ini_get('session.gc_maxlifetime'); self::$time=time(); } public static function start(Memcache $memcache){ self::init($memcache); session_set_save_handler( array(__CLASS__, 'open'), array(__CLASS__, 'close'), array(__CLASS__, 'read'), array(__CLASS__, 'write'), array(__CLASS__, 'destroy'), array(__CLASS__, 'gc') ); session_start(); } public static function open($path, $name){ return true; } public static function close(){ return true; } public static function read($PHPSESSID){ $out=self::$handler->get(self::session_key($PHPSESSID)); if($out===false || $out == null) return ''; return $out; } public static function write($PHPSESSID, $data){ $method=$data ? 'set' : 'replace'; return self::$handler->$method(self::session_key($PHPSESSID), $data, MEMCACHE_COMPRESSED, self::$lifetime); } public static function destroy($PHPSESSID){ return self::$handler->delete(self::session_key($PHPSESSID)); } public static function gc($lifetime){ return true; } private static function session_key($PHPSESSID){ $session_key=self::NS.$PHPSESSID; return $session_key; } } $memcache=new Memcache; $memcache->connect("localhost", 11211) or die("could not connect!"); MemSession::start($memcache);