博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Session && Cookie
阅读量:5939 次
发布时间:2019-06-19

本文共 8846 字,大约阅读时间需要 29 分钟。

hot3.png

Cookie和Session有一些不同:

  1. 存储位置的不同:Cookie将状态保存在客户端,Session将状态保存在服务器端;
  2. 与HTTP协议的关系不同:Cookie需要通过网络传输,依赖于HTTP协议,Session并没有在HTTP的协议中定 义;
  3. 可用性不同:相对于Cookie,Session在客户端禁用Cookie后还可以通过URL回写机制实现Session会话机制。
  4. 安全性不同:因为存储的位置不同,Cookie更容易被篡改,存储在服务器的Session相对来说则安全一些,客户不能随意读取这些内容,除非获到其它用户的了sessionID,这也是XSS攻击会关注的地方。
  5. 同源策略,说到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.name
session.name = PHPSESSID

session 服务端

sessionid

  1. //生成所需的session id,当然后面还需要后续的处理~
  2. //格式为:%.15s%ld%ld%0.8F,每一段的含义如下:
  3. //%.15s    remote_addr ? remote_addr : "" 这一行很容易理解
  4. //%ld        tv.tv_sec    当前的时间戳
  5. //%ld        (long int)tv.tv_usec 当前毫秒数
  6. //%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-sid
session.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);

 

转载于:https://my.oschina.net/20130614/blog/291444

你可能感兴趣的文章
我的友情链接
查看>>
我的友情链接
查看>>
wdcp 安装
查看>>
C语言运算符优先级相关问题
查看>>
MP4视频播放器代码
查看>>
Nginx 匹配 iphone Android 微信
查看>>
MFC_Combo_Box(组合框)控件的用法
查看>>
ldap
查看>>
我的友情链接
查看>>
CentOS 7更改网卡名称
查看>>
Yum软件仓库配置
查看>>
linux 压缩与解压总结
查看>>
mysql脚本1064 - You have an error in your SQL syntax; check the manual
查看>>
nessus 本地扫描(一)
查看>>
linux服务器磁盘陈列
查看>>
交换机配置模式
查看>>
python----tcp/ip http
查看>>
我的友情链接
查看>>
第一本docker书学习笔记1-3章
查看>>
一個典型僵尸網絡淺析
查看>>