http cookie session 介紹 原理以及使用

http協議

http

超文本傳輸協議,無連接,無狀態,

訪問鏈接時,http request 發送請求服務器

http response 響應請求,請求時建立鏈接,請求完成關閉鏈接

keep-alive http持久連接,節省時間,無狀態的所以沒有保存信息,每次傳輸都需要傳輸很大的數據,所以有了會話控制,讓服務器知道我們從一個頁面跳轉過後,還知道連接的請求來源是誰

會話控制

cookie

保存方式

內存cookie:瀏覽器關閉後消失

硬盤cookie:保存在硬盤裏,可以設置過期時間,除非過期或手工刪除,否則是不會消失的

使用場景(永久登錄,購物車)

瀏覽器的小文件保存在硬盤中,服務器端設置,可以通過http響應頭返回給瀏覽器,在響應頭中加入字段 setCookie,

每個瀏覽器都有獨立空間放cookie,在服務器向用戶發送網頁的同時,也會發送cookie,記錄商品信息,訪問另外頁面時,瀏覽器把cookie通過header發送給服務器,於是服務器知道我們訪問了哪些商品,繼續選購,服務器在原來的基礎上繼續追加新的數據,信息,結賬時,把cookie中進行結算

登錄的時候,自動登錄,自動填充用戶名和密碼,第一次登錄時候服務器發送了用戶憑證到硬盤中,後續登錄,客戶端將其一併發送到服務器,服務器驗證是否爲合法用戶

https://blog.csdn.net/p77ll9l53x/article/details/72675645

操作cookie

設置cookie

setcookie("userinfo", "status=1", time()+20, '/practice', '', true);
setcookie ( string $name [, string $value = "" [, int $expire = 0 [, string $path = "" [, string $domain = "" [, bool $secure = false [, bool $httponly = false ]]]]]] ) : bool
$name 名稱
$value 內容
$expire 過期時間 過期時間如果爲0,則爲內存cookie,關閉則過期
$path 保存目錄
$domain 作用域
$secure 是否安全(https)
$httponly 是否只使用http操作cookie,默認falsetrue則不可以用js操作cookie,可以減少xss攻擊

setawcookie 不會對值 進行urlencoding編碼

讀取cookie

$_COOKIE

更新cookie

保持其他參數一樣即可更新
setcookie("userinfo", "status=1", time()+10, '/practice');
setcookie("userinfo", "zhangsanfeng", time()+10, '/practice');

刪除cookie

把時間設置爲已經過期的時間,其他參數也需要一樣,保證$path 和 $domain 和之前的保持一致
setcookie("userinfo", "", time()-1, '/practice');
通過header 操作cookie
header("Set-Cookie:name=value[;expires=date][;domain=domain][;path=path"][;secure][;httponly]);
header('set-Cookie: b=2;expires='.gmdate('D, d M Y H:i:s \G\M\T', time()+3600).'; domain=.test.com');
header('set-Cookie: b=2; path=/test; domain=.test.com; secure; httponly;');
cookie保存數組形式
setcookie('userInfo[name]', 'zhangsan', strtotime("+7 days"));
setcookie('userInfo[sex]', 'man', strtotime("+7 days"));
js 操作cookie
var Cookie = {
  set : function (key, val, expiresDays) {
  	if (expiresDays) {
      var date = new Date();
      date.setTime(date.getTime()+expiresDays*24*3600*1000);
      var expiresStr="expires="+date.toGMTString()+';';
  	}else{
      var expiresStr = '';
  	}
    document.cookie = key + '=' + escape(val)+';' + expiresStr;
  },
  get : function(key){
    var getCookie = document.cookie.replace('/[ ]/g', '');
    var resArr = getCookie.split(';');
    var res;
    for (var i = 0, len = resArr.length; i < len; i++){
      var arr = resArr[i].split('=');
      if (arr[0] == key) {
        res = arr[1];
        break;
      }
    }
    return unescape(res);
  }
}
自動登錄
//判斷前臺自動登錄是否選中...
$row = mysqli_fetch_assoc($result);
if ($autologin == 1){
  setcookie('username', $username, strtotime('+7 days'));
  $salt = 'testsalt';
  $auth = md5($username.$password.$salt).':'.$row['id'];
  setcookie('auth', $auth, strtotime('+7 days'));
}else{
  setcookie('usernmae', $username);
}
//選中了保存cookie登錄成功後,關閉瀏覽器,再次訪問的時候,直接訪問頁面cookie不會消失,此時用cookie中的用戶名在數據庫中進行查找,然後按照一樣的加密規則和cookie中的auth進行比對,如果一致,則直接實現登錄效果
//...
cookie操作類的封裝
<?php

class CustomCookie{
    static private $_instance = null;
    private $expire = 0;
    private $path = '';
    private $domain = '';
    private $secure = false;
    private $httponly = false;
    

    /**
     * 構造函數完成cookie參數初始化工作
     */
    private function __construct(array $options = []){
        $this->setOptions($options);
    }

    private function setOptions(array $options){
        if (isset($options['expire'])) {
            $this->expire = (int)$options['expire'];
        }
        if (isset($options['path'])) {
            $this->path = $options['path'];
        }
        if (isset($options['domain'])) {
            $this->domain = $options['domain'];
        }
        if (isset($options['secure'])) {
            $this->secure = (bool)$options['secure'];
        }
        if (isset($options['httponly'])) {
            $this->httponly = (bool)$options['httponly'];
        }
    }
    /**
     * 單例模式
     * @param [array] $options Cookie相關選項
     * @return object 對象實例
     */
    public static function getInstance(array $options = []){
        if (is_null(self::$_instance)) {
            $class = __CLASS__;
            var_dump($class);
            self::$_instance = new $class($options);
        }
        return self::$_instance;
    }

    /**
     * Undocumented function
     *
     * @param [string] $name cookie名稱
     * @param [string] $value cookie值
     * @param array $options cookie設置參數
     * @return void
     */
    public function set(string $name,mixed $value, array $options=[]){
        if (is_array($options) && count($options) > 0){
            $this->setOptions($options);
        }
        if(is_array($value) || is_object($value)){
            $value = json_encode($value, JSON_FORCE_OBJECT);
        }
        setcookie($name, $value,$this->expire,$this->path, $this->domain, $this->secure, $this->httponly);
    }

    public function get(string $name){
        if (isset($_COOKIE[$name])){
            return substr($_COOKIE[$name],0,1) == '{' ? json_decode($_COOKIE[$name], true) : $_COOKIE[$name];
        }else{
            return null;
        }
    }

    public function del(string $name, array $options = []){
        if (is_array($options) && count($options) > 0){
            $this->setOptions($options);
        }

        if (isset($_COOKIE[$name])){
            setcookie($name, '', time()-1,$this->path, $this->domain, $this->secure, $this->httponly);
            unset($_COOKIE[$name]);
        }
    }

    public function delAll(){
        if (is_array($options) && count($options) > 0){
            $this->setOptions($options);
        }

        if(!empty($_COOKIE)){
            foreach ($_COOKIE as $key => $value) {
                setcookie($key, '', time()-1,$this->path, $this->domain, $this->secure, $this->httponly);
                unset($_COOKIE[$key]);
            }
        }
    }
}
$res =  CustomCookie::getInstance();
$res->set('user', '111',['expire'=>strtotime("+1 days"),'path'=>'/']);
$res->set('userInfo', ['name'=>'zhangsan','age'=>10]);
var_dump($res->get('userInfo'));
cookie的弊端

不要存儲敏感數據,不安全,劫取cookie之後可以用來cookie欺騙

不要把cookie當做客戶端的存儲容器,首先每個域名允許的cookie有限制,根據不同瀏覽器限制不同,最大可以存儲4k

cookie設置之後 每次都會附着在http header中一起發送,浪費帶寬

localStorage

設置:localStorage.setItem(key,value)

讀取:localStorage.getItem(key)

刪除指定:localStorage.removeItem(key)

全部刪除:localStorage.clear()

獲取指定的鍵名:localStorage.key(i)

如果爲json對象需要先轉成字符串:localStorage.setItem(‘userinfo’,JSON.stringify(userinfo))

取出的時候:JSON.parse(localStorage.getItem(userinfo))

特性
生命週期 有服務端生成,可設置失效時間。如果在瀏覽器生成cookie,默認關閉瀏覽器失效 除非清除,否則永久保存 僅在當前會話有效,關閉瀏覽器或頁面清除
存放大小 4k左右 5MB 5MB
與服務器通信 每次都會攜帶http偷,如果使用cookie過多數據會帶來性能問題 客戶端瀏覽器保存,不參與服務器通信 客戶端瀏覽器保存,不參與服務器通信
易用性 需要自己封裝,原生cookie接口不友好 源生接口可以接受,也可以再次封裝對object array良好支持 源生接口可以接受,也可以再次封裝對object array良好支持
使用場景 存在客戶端,管理購物車,h5遊戲 存在客戶端,管理購物車,
Custom_LocalStorage = {
    set : function (key, value){
        var item = {
            data:value
        }
        localStorage.setItem(key, JSON.stringify(item));
    },

    get : function(key) {
        var val = localStorage.getItem(key);
        if (!val) return null;
        val = JSON.parse(val);
        return val;
    }
}

在這裏插入圖片描述

session

什麼是session

持續性的雙向的連接 ,服務器和瀏覽器的保持鏈接的這段時間

session工作原理

在這裏插入圖片描述
理髮店會員卡:髮卡

開始會話:php嘗試在請求中查找會話id,如果不包含就創建新的會話,表示第一次,會話開始之後,php就把數據保存到變量裏$_SESSION,並將其序列化然後發送給會話保存管理器,默認的會話保存管理器是以文件的形式保存,

  1. 準備建立會話的時候,php會先查看請求中是否包含session_id,如果沒有 服務器,服務器會在內存裏創建變量,這個變量就是session_id(session_1234),
  2. 服務器會把session_id發送到瀏覽器保存,一般是保存到cookie中
  3. 以後每次瀏覽器訪問服務器時候,都會攜帶cookie中存在的session_id(session_1234),這樣服務器就認識這個瀏覽器了
  4. 服務器端的session_1234 可以存放任意的會話數據,這些數據是經過序列化之後存放進去的
  5. 每次瀏覽器訪問服務器都可以憑藉自己的session_id 到服務器的變量中認領信息
  6. 如果想銷燬會話,可以刪除掉會話中的數據,還可以銷燬會話文件
php中如何使用會話

開啓會話 session_start()

設置 $_SESSION

銷燬 session_destory()

session名字 session_name()

session的ID session_id()

使用session的生存週期,通過cookie來實現

//設置好後可以實現使用session 但是關閉瀏覽器不過期
setcookie(session_name(),session_id(),time()+3600, '/');
session禁用傳遞session_id

在url中傳參 http://localhost/test.php?session_name()=session_id

在第二個頁面中 獲取session_id($_GET[session_name()]);

銷燬會話
  1. 將$_SESSION 清空

    $_SESSION = [];

  2. 將cookie中的數據清除

    setcookie()

  3. 銷燬會話

    session_destory()

// 初始化會話。
// 如果要使用會話,別忘了現在就調用:
session_start();

// 重置會話中的所有變量
$_SESSION = array();

// 如果要清理的更徹底,那麼同時刪除會話 cookie
// 注意:這樣不但銷燬了會話中的數據,還同時銷燬了會話本身
if (ini_get("session.use_cookies")) {
    $params = session_get_cookie_params();
    setcookie(session_name(), '', time() - 42000,
        $params["path"], $params["domain"],
        $params["secure"], $params["httponly"]
    );
}

// 最後,銷燬會話
session_destroy();
自定義會話管理器

session_set_save_handler() 設置用戶自定義會話存儲

<?php  

CREATE TABLE `sessions` (
  `session_id` char(32) NOT NULL,
  `session_data` varchar(255) NOT NULL,
  `session_expire` varchar(255) NOT NULL,
  PRIMARY KEY (`session_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


class CustomSession implements SessionHandlerInterface
{
    private $link;
    private $lifetime;
    public function open($savePath, $session_name){
        $this->lifetime = get_cfg_var('session.gc_maxlifetime');
        $this->link = mysqli_connect('localhost', 'root', 'root');
        mysqli_set_charset($this->link, 'utf8');
        mysqli_select_db($this->link, 'session_test');
        if ($this->link){
            return true;
        }
        return false;
    }

    public function close(){
        mysqli_close($this->link);
        return true;
    }

    public function read($session_id){
        $session_id = mysqli_escape_string($this->link, $session_id);
        $sql = "SELECT * FROM sessions WHERE session_id = '{$session_id}'";
        $result = mysqli_query($this->link, $sql);
        if(mysqli_num_rows($result) == 1){
            return mysqli_fetch_assoc($result)['session_data'];
        }
        return '';
    }

    public function write($session_id, $session_data){
        $session_id = mysqli_escape_string($this->link, $session_id);
        $sql = "SELECT * FROM sessions where session_id = '{$session_id}'";
        $result = mysqli_query($this->link, $sql);

        $newExp = time() + $this->lifetime;
        var_dump($newExp);
        var_dump(mysqli_num_rows($result));
        if(mysqli_num_rows($result) == 1){
            $sql = "UPDATE sessions SET session_expire='{$newExp}', session_data = '{$session_data}' where session_id = '{$session_id}'";
        }else{
            $sql = "INSERT sessions VALUES('{$session_id}','{$session_data}','{$newExp}')";
        }
        mysqli_query($this->link, $sql);
        return mysqli_affected_rows($this->link) == 1;
    }

    public function destroy($session_id){
        $session_id = mysqli_escape_string($this->link, $session_id);
        $sql = "DELETE FROM sessions WHERE session_id = '{$session_id}'";
        mysqli_query($this->link, $sql);
        return mysqli_affected_rows($this->link) == 1;
    }

    public function gc($maxlifetime){
        $sql = "DELETE FROM sessions WHERE session_expires <" . time();
        mysqli_query($this->link, $sql);
        if (mysqli_affected_rows($this->link) > 0) {
            return true;
        }
        return false;
    }
}

// 使用說明:new之後,要設置保存方式爲用戶
// require_once 'CustomSession.php';
// 要實現接口中的所有方法,才能使用
$customsession = new CustomSession;

ini_set('session.save_handler', 'user');
session_set_save_handler($customsession, true);

session_start();
$_SESSION['user_name'] = 'liming';
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章