- 1 什麼是會話控制
- 出現原因:http是無狀態協議的,每次都是不同的服務器請求,無法維護兩個請求事務之間的關係.
- 會話控制:能夠在網站中跟蹤一個變量,通過對變量的跟蹤,就可以使多個請求事物之間建立聯繫,根據授權和用戶身份顯示不同的內容,不同頁面
- cookie:是服務器設置在客戶端的文本文件,保存客戶端得個人信息.
- 2 會話跟蹤技術
- 1 隱藏表單域
- 2 url重寫
- 3 cookie技術
- 4 session技術
- 隱藏表單技術:
- <input type="hidden" name="name" value="設置隱藏值">,在gethuopost方法中指定指定有關消息的會話名稱和值
- url(統一資源定位)重寫:
- 將唯一會話的id添加到url結尾,來進行標識
- http://www.lampbrother.net?id=1000
- cookie:將唯一的會話id存放在客戶端
- session:將唯一的會話id存放在服務器端
- 2 會話跟蹤方式
- 第一:通過url傳遞參數,使用超鏈接或者header()函數
- 第二:使用隱藏表單域,提交給php腳本
- 第三:使用Cookie將用戶的信息存儲在客戶端文件中
- 第四:使用Session將用戶的信息存儲在服務器端的信息存儲在服務器端
- 4 Cookie:
- 1 Cookie的介紹:
- 1 cookie是在http協議下,服務器或腳本在客戶端保存維護信息的一種方式
- 2 cookie是web服務器保存在客戶端的一個很小的文本文件,保存客戶端的信息,提高網頁的處理效率,降低服務器負擔
- 3 cookie保存在客戶端,通常在瀏覽器的cookie臨時文件夾中,可以手動的刪除.如果cookie太多超過系統的允許範圍,系統將自動刪除
- 2 cookie的工作原理
- 1 當用戶訪問基於php技術的網站時,在php中可以使用setcookie()函數生成一個cookie,系統經過處理,將cookie發送到客戶端並保存在C:\Documents and Setting\用戶名\Cookies目錄下
- 2 cookie是http標頭的一部分,在它之前不能有任何輸出空格和換行都不可以
- 3 當客戶端再次訪問網站時,瀏覽器會自動把cookie目錄下與該站點對應的cookie信息發送到服務器,服務器將自動把客戶端傳來的cookie轉化成php的變量,.php5中存放在$_COOKIE全局數據中
- 4 接受和處理cookie.使用$_COOKIE獲取
- Setcookie()爲頭信息設置,在此之前不能有任何輸出
- boolsetcookie( string $name [, string $value [, int $expire = 0 [, string $path [, string $domain [, bool $secure = false [, bool $httponly = false ]]]]]] )
- Name:調用名爲cookiename的cookie
- value :name對應的值
- exprice :設置cookie的過期時間和日期,用一個標 準的Unix時間標記,可以用time()函數取得,以秒爲單位.
- path :服務器端的有效路徑,設置爲“/”表示這個域中所有數組都可以被訪問讀取。
- Domain:設定cookie有效域名
- secure :指明cookie只能通過安全的https傳送, 設爲true時只能通過安全的https,默認爲false.即設置是否僅在https安全連接時才發送cookie到客戶端:0或 1
- 刪除cookie:
- 1 調用一個參數名爲已經存在的cookied的名稱,則刪除就會刪除cookie
- 2 設置cookie的失效時間爲time()或者time()-1
- 注意:當cookie被刪除時,它的值在當前頁面仍然有效.如果要把cookie設置成在瀏覽器關閉後就失效.那麼可以吧expiretime的值設爲0,或者不設此值
- /*設置cookie*/
- $time=time()+3600;//設置時間爲一個小時
- //保存變量
- setcookie('username','admin',$time);
- setCookie('password','123456',$time);
- //保存數組
- setCookie("cookie[one]",'coo1',$time);
- setCookie("cookie[two]",'coo2',$time);
- /*刪除cookie*/
- //方式1:設置值爲空
- setCookie('username',"");
- setCookie('cookie[one]',"");
- //方式1:設置過期時間
- setCookie('password',"coo1",time()-1);
- setCookie('cookie[two]',"coo2",time()-1);
- if(isset($_COOKIE)){
- }
- 3 COOKIE的注意事項
- 1 setcookie()之前不能有任何的輸出,空白和空格也不行(Setcookie()爲頭信息設置)
- 2 setcookie()之後在當前頁面echo時不會輸出,必須刷新或到下一個頁面纔會輸出
- 3 不同瀏覽對cookie的處理不同,客戶端可以禁用cookie,而且對瀏覽器的數量有限制.一個瀏覽器可以最多創建300個cookie,每個不能超過4kb,每個站點最多設置20個
- 4 避免過度依賴cookie,因爲客戶端會禁止掉cookie
- 7 session
- 1 什麼是session?
- 1 session從用戶訪問頁面開始,到斷開與網站的連接爲止,形成一個會話的生命週期.在會話期間,分配客戶唯一的一個sessionID,用來標識當前用戶,與其他用戶進行區分
- 2 session會話時,session會分別保存在客戶端和服務器端得兩個文職,對於客戶端:使用臨時的cookie保存(cookie的名稱爲PHPSESSID)或者通過url字符串的形式傳遞.服務器端也以文本的形式保存在指定的session目錄中
- 3 session通過id接受每一次訪問的請求,從而識別當前用戶,跟蹤和保持用戶的具體資料,以及session變量,可在session中國存儲數字或文字資料.比如session_name.這些信息都保存在服務器端
- 4 sessionID可以作爲會話信息保存到數據庫中,進行session持久化.這樣可以跟蹤用戶的登陸次數,在線與否,在線時間
- 2 cookie和session的區別:
- 相同點:都可以在解決http無狀態的問題,使同一個客戶端在訪問網站的多次請求中,可以保存,設置信息,並且在整個web應用中共享
- 不同:
- cookie的信息保存在客戶端
- session:保存在服務器端
- 聯繫:當使用基於cookie的session時,session DI一般保存在cookie中
- 3 設置session
- 1 開啓會話
- session_start() 功能 : 1開始一個會話,2 返回已經存在會話
- 說明:這個函數沒有參數,且返回值爲true,如果使用基於cookie的sessin,那麼在session_satrt()之前不能有任何的輸出,包括空白
- 2 註冊會話
- php5 使用$_SESSION['KEY']=VALUE方式,類似於GET,POST,COOKIE
- 3 使用會話之前必須session_start()啓動會話,這樣就可以使用$_SEESION超全局數組訪問變量了
- 判斷是否設置session
- if(isset($_SESSION))...;
- 如果在php.ini中session.auto_start=1;開啓,則在每個頁面執行session_start(),不需要手工設置.
- 缺點:不能將對象放入session中
- //開啓一個session會話,或者返回已經存在的session
- session_start();
- //這隻session
- $_SESSION['USER']='admin';
- $_SESSION['username']='admin_root';
- //獲得session_id()
- //1 PHPSESSID
- echo $_COOKIE['PHPSESSID'].'<br>';
- //2 session_name()
- echo $_COOKIE[session_name()].'<br>';
- //3 session_id()
- echo session_id().'<br>';
- 4 銷燬session
- 註銷變量:
- 1 unset($_SESSION['XXX']):用於刪除單個session變量
- 注意:不要使用unset($_SESSION),此函數不可用,會刪除全局的$_SESSION銷燬
- 2 $_SESSION=array():刪除多個session變量
- 3 session_unset():刪除所有的session變量
- 銷燬session_destroy():結束當前的會話,並清空會話中的所有資源.該函數不會unset(釋放)和當前session相關的全局變量,也不會刪除客戶端的session cookie
- //返回已經存在的session
- session_start();
- //清空session值
- $_SESSION=array();
- //如果是基於Cookie的session,則清空cookie中的session_id()
- if(isset($_COOKIE[session_name()])){
- // '/':在php.ini中年的cookie.path='/';
- setCookie($_COOKIE[session_name()],'',time()-3600,'/');
- }
- //銷燬session
- session_destroy();
- 注:php默認的session是基於cookie的,如果要刪除cookie的話,必須藉助setcookie()函數
- 5 保存session數據
- 1 保存基本數據類型
- 2 保存數組
- 3 保存對象
- session_start();
- //存取標量
- $_SESSION['USER']='ADMIN';//STRING
- $_SESSION['COUNT']=10;//INT
- $_SESSION['PRICE']=99.99;//FLOAT
- $_SESSION['IS_GOOD']=true;//BOOLEAN
- //存取數組
- $_SESSION['USER_INFO']=array('username'=>'root','password'=>123456);
- //存取對象
- class Person{public $name='admin';public $age=23; }
- $_SESSION['OBJ']=new Person;
- 函數:
- 1 session_id():用於獲取或取得當前的session的唯一標識符號SID,php5中既可以附加載url取得當前會話的session_id和session_name
- SID:即使是一個字符串session_name()=session_id();
- 解釋:
- a 如果session_id()有具體指定的值得話,將取代當前的session_id值.當cookie沒有被禁用時,如果指定了一個session_id()值,每次啓動session_start()都會網客戶端發送一個cookie值.不論當前SESSION_ID值是否與指定值相等
- b 如果session_id()沒有指定的值,則返回當前的SESSIONID,當前會話沒有開啓則返回空字符串
- c 使用該函數必須在session_start()之前
- <?php
- //在session_start()之前設置session_id()
- session_id('lamp');
- session_start();
- echo '當前的session_id()爲:'.session_id().'<br>';//輸出lamp
- ?>
- 2 session_regenerate_id():該函數更換當前的session_id,但不改變當前的session信息
- 返回值:bool型
- session_id:命名規則[a-z, A-Z, 0-9 and '-,' ]
- //設置session_id=old_session[a-z, A-Z, 0-9 and '-,' ]
- session_id('old-session');
- $old_session_id=session_id();
- session_start();
- //更改session_id=new_session
- session_regenerate_id('new-session');
- $new_session_id=session_id();
- $_SESSION['USER']='ADMIN';//STRING
- echo '原來的session_id:'.$old_session_id.'<br>';
- echo '新的的session_id:'.$new_session_id.'<br>';
- print_r($_SESSION);
- 3 session_name():獲取或者更改當前的session_name,注意:不能只有數字組成,必須至少包含一個字母,否則每時每刻會生成新的session_id
- 注意: session_id()和session_name()都要在session_start()之前設置
- session_id('lamp2012');
- session_name('mySession');
- session_start();
- $_SESSION['USER']='ADMIN';//STRING
- echo 'session_id:'.session_id().'<br>';
- echo 'session_name:'.session_name().'<br>';
- print_r($_SESSION);
- 6 session跨頁傳遞的三種問題:
- 1 客戶端禁用了cookie
- 2 瀏覽器出現了問題無法存儲cookie
- 3 php.ini中的session.user_trans_sid=0或者編譯時沒有打開--enable-trans-sid選項
- 解決的三條途徑:
- 1 在php.ini中開啓session.user_trans-sid=1,或者編譯時打開--enable-trans-sid選項,讓php自動跨頁傳遞session_id
- 2 手動通過url傳值,隱藏表單傳遞session_id
- <a href="index.php?<?php echo SID?>">sid</a>
- <a href="index.php?<?php echo session_name().'='.session_id()?>">sid</a
- 3 用文件,數據庫等形式保存sessin_id,在跨頁過程中手工調用
- 7 持久化session
- 1 請求結束後所有的註冊變量都會自動被序列化(爲了方便保存到服務器端得會話文本文件中),獲取的時候在進行還原
- 手動編碼:
- session_encode():序列號-編碼
- session_decode():還原-解碼
- 警告:有些類型的數據不能被序列化因此也就不能保存.包括resource變量和有循環引用的對象
- 9 配置會話控制
- session.auto_start=0;//在請求啓動時初始化
- session.auto_start=0;//無需每次手動sessin_start(),不過該選項有一些限制,不能將對象放入會話,因爲類的定義必須在會話之前加載在會話中重建對象
- session.cache_expire=180;//設置緩存中的會話過期時間在n分鐘後
- session.cookie_lifetime=0;//設置按秒記的cookie的保存時間,0表示知道瀏覽器被重啓
- session.cookie_path=/;//cookie的有效路徑
- session.cookie_domain=;//cookie的有效域
- session.name=PHPSSESID;//又在cookie裏的session_name()
- session.save_hander=files;//用於保存/取回數據的控制方式
- session.save_path=/tmp;//在save_handler設爲文件是傳給控制器的參數,這是數據文件的保存路徑
- session.user_cookie=1;//是否使用cookies
- session.gc_maxlifetime=40;//指定過了多少秒之後數據就會被視爲“垃圾”,並被清楚
- session.gc_probability=1//
- session.gc_divisor=100;//這兩個合起來就是啓動gc進程管理概率的,在session初使化時(session_start())
- session.gc_probability/session.gc_divisor:1/100,在session_start100次,有一次的概率刪除垃圾文件
- 10 用文件保存session信息
- 1: 將php.ini中的session.save_handler的cookie保存方式選項user
- 2: 設置session操作中的回調函數,在session_start()之前使用session_set_save_handler('open','close','read','write','destroy','gc');
- 3: 開啓session_start();
- 函數解析:
- open($session_path,$session_name):在session_start()時啓動,返回true
- close():session_close()和session_destroy()時調用,return true
- read($session_id):session_start()時和從$_SESSION取值的時調用,return true
- write($session_id,$session_data):在session_write_close()強制將數據寫入到$_SESSION全局數組中時調用,return true;
- destroy($session_id):在執行session_destroy()自動調用,return true
- gc($session_gc_lifetime):在執行session_start().read(),write()時自動調用,return true
- //參數:$save_path,$session_name
- function open($save_path, $session_name){
- //設置全局的session信息保存路徑
- global $sess_save_path;
- //爲session的保存路徑賦值
- $sess_save_path=$save_path;
- return true;
- }
- //session_write_close()和session_destroy()時調用
- function close(){
- //在銷燬和關閉寫入時,不進行任何操作,返回true
- return true;
- }
- //在session_start(),$_SESSION,將session數據讀取到$_SESSION中時
- //參數:session_id
- function read($id){
- //獲得全局的session保存路徑
- global $sess_save_path;
- //拼接所需的文件路徑名稱
- $sess_file=$sess_save_path.'/king_'.$id;
- //返回文件的信息,沒有文件時返回false
- return (string)@file_get_contents($sess_file);
- }
- //結束時和session_write_close()強制將SESSION數據防止在$_SESSION全局變量時
- function write($id,$sess_data){
- global $sess_save_path;
- $sess_file=$sess_save_path.'/king_'.$id;
- //以w模式打開文件
- if($fp=@fopen($sess_file,'w')){
- 將session信息寫入指定的資源中
- $return=fwrite($fp,$sess_data);
- fclose($fp);
- return $return;
- }else{
- return false;
- }
- }
- //在destroy時調用
- function destroy($id){
- global $sess_save_path;
- $sess_file=$sess_save_path.'/king_'.$id;
- //刪除session路徑下指定的session信心
- return @unlink($sess_file);
- }
- //在session_start(),read(),write()時
- function gc($maxlifetime){
- global $sess_save_path;
- //glob — 尋找與模式匹配的文件路徑,返回數組
- //將路徑寫的所有超過gc生命週期的文件刪除
- foreach(glob($sess_save_path.'/king_*') as $filename){
- if(filemtime($filename)+$maxlifetime < time()){
- @unlink($filename);
- }
- }
- return true;
- }
- @session_set_save_handler('open','close','read','wite','destroy','gc');
- @session_start();
- 11 將session信息保存到數據庫
- sql:測試表
- create table session(
- PHPSSESID char(32), //session_id
- update_time int(10), //文件的gc_maxlifetime
- client_ip char(15), //客戶端ip地址
- data text) //session信息
- 1:設置session.save_handler=user;//自定義session存儲方式
- 2 session.gc_maxlifetime=time;//gc回收垃圾的時間
- 3 在session_start()之前調用session_set_save_handler('open','close','read','write','destroy','gc');
- 4 寫session處理類,靜態屬性和方法
- 5 開啓session_start();
- <?php
- //session_set_save_handler
- class Session{
- private static $handler=null;//傳進來的pdo句柄
- private static $client_ip=null;//客戶端ip
- private static $lifetime=null;//生存時間(session.gc_maxlifetime)
- private static $time;//訪問時的時間戳
- //設置初始化參數
- private static function init($handler){
- self::$handler=$handler;
- self::$client_ip=!empty($_SERVER['REMOTE_ADDR'])?$_SERVER['REMOTE_ADDR']:"unKnown";//設置客戶端的ip地址
- self::$lifetime=ini_get('session.gc_maxlifetime');//gc回收垃圾的最大生命週期
- self::$time=time();
- }
- //設置自定義的session處理方式,並開啓session_start()
- public static function start(PDO $pdo){
- self::init($pdo);//設置當前使用的pdo句柄
- //__CLASS__:php起,返回類的名稱
- session_set_save_handler(
- array(__CLASS__,'open'),
- array(__CLASS__,'close'),
- array(__CLASS__,'read'),
- array(__CLASS__,'write'),
- array(__CLASS__,'destroy'),
- array(__CLASS__,'gc')
- );
- //開啓session
- session_start();
- }
- //open處理方法,不進行任何操作,返回true
- public static function open($session_path,$session_name){
- return true;
- }
- //close處理方法,不進行任何操作,返回true
- public static function close(){
- return true;
- }
- //讀取session數據的操作
- public static function read($session_id){
- $sql='select update_time,client_ip,data from session where PHPSSESID="'.$session_id.'"';
- $stmt=self::$handler->prepare($sql);
- $stmt->execute(array($session_id));
- $result=$stmt->fetch(PDO::FETCH_ASSOC);
- //沒有查詢結果返回:''
- if(!$result){
- self::destroy($session_id);
- return "";
- }
- //ip地址有誤返回:''
- if($result['client_ip'] != self::$client_ip){
- self::destroy($session_id);
- return '';
- }
- //數據合法返回數據
- return $result['data'];
- }
- //寫入數據庫
- public static function write($session_id,$session_data){
- $sql_select='select PHPSSESID,update_time,client_ip,data from session where PHPSSESID="'.$session_id.'"';
- $stmt=self::$handler->prepare($sql_select);
- $stmt->execute();
- //數據已經存在記錄則更新
- if($result=$stmt->fetch(PDO::FETCH_ASSOC)){
- if($result['data'] != $session_data || self::$time > ($result['update_time']+10)){
- $sql_update='update sessoin set update_time=?,data=? where PHPSSESID="'.$session_id.'"';
- $stmt_update=self::$handler->prepare($sql_update);
- if($stmt_update->execute(array(self::$time,$session_data))){
- return true;
- }
- }
- }else{
- //數據不存在記錄則插入記錄
- if(!empty($session_data)){
- $sql_insert='insert into session(PHPSSESID,update_time,client_ip,data) values(?,?,?,?)';
- $stmt_insert=self::$handler->prepare($sql_insert);
- if($stmt_insert->execute(array($session_id,self::$time,self::$client_ip,$session_data))){
- return true;
- }
- }
- }
- }
- //調用該方法刪除指定的session信息
- public static function destroy($session_id){
- $sql='delete from session where PHPSSESID="'.$session_id.'"';
- $stmt=self::$handler->prepare($sql);
- if($stmt->execute(array($session_id))){
- return true;
- }
- }
- //超過最大生命週期的時候刪除數據
- static function gc($session_gc_maxlifetime){
- $sql="delete from session where update_time <?";
- $stmt=self::$handler->prepare($sql);
- $stmt->execute(array(self::$time-$session_gc_maxlifetime));
- return true;
- }
- }
- try{
- $pdo=new PDO('mysql:host=localhost;dbname=demo;charset=utf8','root','123456');
- }catch(PDOException $e){
- echo $e->getMessage();
- }
- Session::start($pdo);
- ?>
- 12 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!");
session機制詳解(thinkphp)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.