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';
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章