博客列表 >PHP第二十三天作业-使用Cookie和Session登陆实例-2018-05-07

PHP第二十三天作业-使用Cookie和Session登陆实例-2018-05-07

HeartofSunny的博客
HeartofSunny的博客原创
2018年05月07日 00:21:16943浏览
cookie
index,php
<?php
    $page_title='首页';
    include ('inc/header.php');
    echo '<h2 style="color:red">我是首页</h2>';
    if ((isset($_COOKIE['user_id'])) && basename($_SERVER['PHP_SELF']) != 'logout.php') {
        echo '<a href="logout.php">退出</a>';
    }else {
        echo '<a href="login.php">登录</a>';
    }
    include ('inc/footer.php');

loggedin.php
<?php
    if(!isset($_COOKIE['user_id'])){
        require ('inc/function.php');

        //跳转到默认首页
        redirect_user();
    }

    //如果已经登录
    //设置页面标题
    $page_title = '已经登录';
    include ('inc/header.php');

    //打印欢迎信息,并提供退出功能
    echo <<< "WELCOME"
    <h2 style="color:red">登陆成功</h2>
    <p>欢迎您: {$_COOKIE['user_name']}</p>
    <p><a href="logout.php">退出</a></p>
WELCOME;

    //加载底部
    include ('inc/footer.php');

login.php
<?php

if ($_SERVER['REQUEST_METHOD']=='POST'){
    //加载公共函数库
    require ('inc/function.php');
    //连接数据库
    require ('inc/connect.php');
    //验证登陆
    list($check,$data) = check_login($dbc,$_POST['email'],$_POST['password']);

    //验证通过
    if($check){
        //设置cookies
        setcookie('user_id',$data['user_id']);
        setcookie('user_name',$data['user_name']);

        //跳转页面
        redirect_user('loggedin.php');
    }else{
        //验证失败
        $errors = $data;
    }

    //关闭数据库连接
    mysqli_close($dbc);
}

//加载
include('login_page.php');

login_page.php
<?php
$page_title = '用户登录';

//加载头部文件
include('inc/header.php');

//打印错误信息
if (isset($errors) && !empty($errors)) {
    $errors_msg = '<p style="color:red">';
    foreach ($errors as $msg) {
        $errors_msg .= $msg.'<br>';
    }
    echo $errors_msg.'</p>';
}
?>
    <h2 style="color:red">用户登录</h2>
    <form action="login.php" method="post">
        <p>
            <label for="email">邮箱:</label>
            <!--使用粘性表单技术在文本框中显示用户之前输入的内容,提升用户体验-->
            <input type="email" name="email" id="email" value="<?php echo  isset($_POST['email'])?$_POST['email']:'' ?>">
        </p>
        <p>
            <label for="password">密码:</label>
            <input type="password" name="password" id="password" value="<?php echo  isset($_POST['password'])?$_POST['password']:'' ?>">
        </p>
        <p><button type="submit" name="submit" id="submit">登录</button></p>
    </form>

<?php include ('inc/footer.php'); //加载底部 ?>

logout.php
<?php
    if (!isset($_COOKIE['user_id'])) {
        require ('inc/function.php');
        //跳转到默认首页
        redirect_user();
    } else {  //删除cookies
        setcookie('user_id', '', time()-3600);
        setcookie('user_name','', time()-3600);
    }

    //设置页面标题
    $page_title = '已经登录';
    include ('inc/header.php');

    //打印退出信息,并提供登录功能
    echo <<< "WELCOME"
    <h2 style="color:red">退出成功</h2>
    <p><a href="login.php">登录</a></p>
WELCOME;

    include ('inc/footer.php');
    
inc/connect.php
<?php
//创建连接参数: 因为连接参数不会经常变化,所以推荐使用常量
define ('DB_HOST', 'localhost');
define ('DB_USER', 'root');
define ('DB_PASS', 'root');
define ('DB_NAME', 'php');
define ('DB_CHAR', 'utf8');

$dbc = @mysqli_connect(DB_HOST, DB_USER, DB_PASS, DB_NAME);

//连接失败一定会返回错误编号,可以根据编号判断,也可用 $db是否为false进行判断
if (mysqli_connect_errno($dbc)) {
    echo '连接失败'.mysqli_connect_error($dbc);
}

mysqli_select_db($dbc, DB_NAME);  //选择要操作的数据库
mysqli_set_charset($dbc, DB_CHAR); //设置客户端默认字符编码集

inc/footer.php
<h3>我是公共底部的代码</h3>
</body>
</html>

inc/function.php
<?php
//登陆公共函数库
function redirect_user($page = 'index.php'){
    //默认url格式
    $url = 'http://'.$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']);
    //如果有,去掉url右侧的斜线
    $url = rtrim($url,'/\\');
    //添加上当前的脚本名称,默认为:index.php
    $url .= '/'.$page;
    //跳转到指定目标地址
    header('Location:'. $url);
    //退出当前函数,这是一个好习惯,否则后面代码仍会执行,仅仅不会在当前页面输出罢了
    exit();
}

//验证用户登陆
function check_login($dbc,$email='',$password=''){
    //初始化错误信息组
    $errors = [];
    //验证邮箱
    if(empty($email)){
        $errors[] = '邮箱地址不能为空';
    }else {
        $e = mysqli_real_escape_string($dbc, trim($email));
    }

    //验证密码
    if (empty($password)) {
        $errors[] = '密码不能为空';
    } else {
        $p = mysqli_real_escape_string($dbc, trim($password));
    }

    //非空验证通过,即$error数组为空
    if (empty($errors)) {
        //根据邮箱与密码来查询用户id与用户名
        $sql = "SELECT `user_id`,`user_name` FROM `user` WHERE `email`='$e' AND `password`=sha1('$p') ";
        //执行查询
        $res = mysqli_query($dbc, $sql);
        //查询成功应该返回唯一一条记录
        if (mysqli_num_rows($res) == 1) {
            //将查询结果解析到数组中
            $row = mysqli_fetch_array($res, MYSQLI_ASSOC);
            //返回查询结果
            return [true, $row];
        } else {
            //查询失败
            $errors[] = '邮箱或密码不正确,请重新输入';
        }
    }
    return [false, $errors];
}

inc/header.php
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
 content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>
        <?php
 //设置当前的页面标题
 echo isset($page_title) ? $page_title :'默认标题';
 ?>
 </title>
</head>
<body>
    <h3>我是公共头部的代码</h3>

总结:


1.cookie是什么东西

  cookie是php会话技术之一,cookie是浏览器保存在客服端存储设备上的txt文件的有关用户访问某个网站保

  留的有关信息,如用户名、密码、上次访问时间、上次访问内容等等。

2.php的cookie工作原理

  在php中,浏览器保存cookie的动作是由服务端发出指令的,内容也是服务端指定的。当从浏览器向服务器发

  出页面请求后,服务器接受请求、处理请求,并响应请求,在向用户返回请求结果时,若需要保存一些用户访

  问的信息,服务端通过setcookie指令告诉浏览器要保存cookie信息。浏览器在接受到服务器的响应后,将

  cookie保存在默认目录下的某个txt文件中。浏览器在向某个网站发送请求前,首先检查是不是有该网站的

  cookie信息,如果有,则需要将cookie信息加载到HTTP请求中发送给服务器,这是HTTP协议规定的浏览器/服

  务器响应机制。

3.cookie增删改查代码:

  ¤如何添加一个cookie:

  在php页面php脚本中是:setcookie($key,$value,expiretime);//第一个参数是保存的cookie信息的键,第

                                     //二个参数是对应于$key键的值,cookie的本质就是一条一条的键

                                    //值对。三个参数是cookie的过期时间,单位是秒,一般用现在的时

                                     //间加上要保留的秒数,如time()+7*24*3600;即保持7周

   说明:一个网站可以保存多个cookie信息,只要在服务端设置好相应的键值对,cookie只能保存字符串信 

   息,不能保存对象。cookie文件中的多个不同cookie信息即键值对可以有不同的过期时间。浏览器在向服

   务器发送请求时会分别处理

   如何更改cookie信息:

   还是通过setcookie,本质就是用新的键值对覆盖原有的键值对,在用setcookie的时候,键名是要修改的键

   名;setcookie("原来的键","原来的值",过期时间);更改:setcookie("原来的键","新值",过期时间);

   删除cookie信息:

   仍然用setcookie,将要删除的cookie键值对的值设为空,将过期时间设置为一个过去的时间,即将这个

   cookie信息删除,如果删除了所有的cookie,则浏览器会将整个cookie文件都删除。

   查询cookie信息:

   查询是在服务端进行的,通过预定义的超全局数组$_COOKIE以及相应的键就可以访问到相应的cookie信息。


Session

index.php
<?php
//开启会话
session_start();
    $page_title='首页';
    include ('inc/header.php');
    echo '<h2 style="color:red">我是首页</h2>';
    if ((isset($_SESSION['user_id'])) && basename($_SERVER['PHP_SELF']) != 'logout.php') {
        echo '<a href="logout.php">退出</a>';
    }else {
        echo '<a href="login.php">登录</a>';
    }
    include ('inc/footer.php');
    
loggedin.php
<?php
//开启会话
session_start();
    if(!isset($_SESSION['user_id'])){
        require ('inc/function.php');

        //跳转到默认首页
        redirect_user();
    }

    //如果已经登录
    //设置页面标题
    $page_title = '已经登录';
    include ('inc/header.php');

    //打印欢迎信息,并提供退出功能
    echo <<< "WELCOME"
    <h2 style="color:red">登陆成功</h2>
    <p>欢迎您: {$_SESSION['user_name']}</p>
    <p><a href="logout.php">退出</a></p>
WELCOME;

    //加载底部
    include ('inc/footer.php');
    
login.php
<?php
//开启会话
session_start();
if ($_SERVER['REQUEST_METHOD']=='POST'){
    //加载公共函数库
    require ('inc/function.php');
    //连接数据库
    require ('inc/connect.php');
    //验证登陆
    list($check,$data) = check_login($dbc,$_POST['email'],$_POST['password']);

    //验证通过
    if($check){
        //设置cookies
        $_SESSION['user_id'] = $data['user_id'];
        $_SESSION['user_name'] = $data['user_name'];

        //跳转页面
        redirect_user('loggedin.php');
    }else{
        //验证失败
        $errors = $data;
    }

    //关闭数据库连接
    mysqli_close($dbc);
}

//加载
include('login_page.php');

login_page.php
<?php
$page_title = '用户登录';

//加载头部文件
include('inc/header.php');

//打印错误信息
if (isset($errors) && !empty($errors)) {
    $errors_msg = '<p style="color:red">';
    foreach ($errors as $msg) {
        $errors_msg .= $msg.'<br>';
    }
    echo $errors_msg.'</p>';
}
?>
    <h2 style="color:red">用户登录</h2>
    <form action="login.php" method="post">
        <p>
            <label for="email">邮箱:</label>
            <!--使用粘性表单技术在文本框中显示用户之前输入的内容,提升用户体验-->
            <input type="email" name="email" id="email" value="<?php echo  isset($_POST['email'])?$_POST['email']:'' ?>">
        </p>
        <p>
            <label for="password">密码:</label>
            <input type="password" name="password" id="password" value="<?php echo  isset($_POST['password'])?$_POST['password']:'' ?>">
        </p>
        <p><button type="submit" name="submit" id="submit">登录</button></p>
    </form>

<?php include ('inc/footer.php'); //加载底部 ?>

logout.php
<?php
//开启会话
session_start();
    if (!isset($_SESSION['user_id'])) {
        require ('inc/function.php');
        //跳转到默认首页
        redirect_user();
    } else {  //删除SESSION
        $_SESSION = [];
        session_destroy();
        setcookie('PHPSESSID', '', time()-3600);
    }

    //设置页面标题
    $page_title = '已经登录';
    include ('inc/header.php');

    //打印退出信息,并提供登录功能
    echo <<< "WELCOME"
    <h2 style="color:red">退出成功</h2>
    <p><a href="login.php">登录</a></p>
WELCOME;

    include ('inc/footer.php');
    
inc/connect.php
<?php
//创建连接参数: 因为连接参数不会经常变化,所以推荐使用常量
define ('DB_HOST', 'localhost');
define ('DB_USER', 'root');
define ('DB_PASS', 'root');
define ('DB_NAME', 'php');
define ('DB_CHAR', 'utf8');

$dbc = @mysqli_connect(DB_HOST, DB_USER, DB_PASS, DB_NAME);

//连接失败一定会返回错误编号,可以根据编号判断,也可用 $db是否为false进行判断
if (mysqli_connect_errno($dbc)) {
    echo '连接失败'.mysqli_connect_error($dbc);
}

mysqli_select_db($dbc, DB_NAME);  //选择要操作的数据库
mysqli_set_charset($dbc, DB_CHAR); //设置客户端默认字符编码集

inc/footer.php
<h3>我是公共底部的代码</h3>
</body>
</html>

inc/function.php
<?php
//登陆公共函数库
function redirect_user($page = 'index.php'){
    //默认url格式
    $url = 'http://'.$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']);
    //如果有,去掉url右侧的斜线
    $url = rtrim($url,'/\\');
    //添加上当前的脚本名称,默认为:index.php
    $url .= '/'.$page;
    //跳转到指定目标地址
    header('Location:'. $url);
    //退出当前函数,这是一个好习惯,否则后面代码仍会执行,仅仅不会在当前页面输出罢了
    exit();
}

//验证用户登陆
function check_login($dbc,$email='',$password=''){
    //初始化错误信息组
    $errors = [];
    //验证邮箱
    if(empty($email)){
        $errors[] = '邮箱地址不能为空';
    }else {
        $e = mysqli_real_escape_string($dbc, trim($email));
    }

    //验证密码
    if (empty($password)) {
        $errors[] = '密码不能为空';
    } else {
        $p = mysqli_real_escape_string($dbc, trim($password));
    }

    //非空验证通过,即$error数组为空
    if (empty($errors)) {
        //根据邮箱与密码来查询用户id与用户名
        $sql = "SELECT `user_id`,`user_name` FROM `user` WHERE `email`='$e' AND `password`=sha1('$p') ";
        //执行查询
        $res = mysqli_query($dbc, $sql);
        //查询成功应该返回唯一一条记录
        if (mysqli_num_rows($res) == 1) {
            //将查询结果解析到数组中
            $row = mysqli_fetch_array($res, MYSQLI_ASSOC);
            //返回查询结果
            return [true, $row];
        } else {
            //查询失败
            $errors[] = '邮箱或密码不正确,请重新输入';
        }
    }
    return [false, $errors];
}

inc/header.php
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
 content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>
        <?php
 //设置当前的页面标题
 echo isset($page_title) ? $page_title :'默认标题';
 ?>
 </title>
</head>
<body>
    <h3>我是公共头部的代码</h3>

总结:

首先,我们为什么需要Session,就是因为我们需要存储各个用户的状态数据。

一、默认机制,用磁盘文件来实现PHP会话。php.ini配置:session.save_handler = files

session执行流程

1,session_start()

    A、 session_start()是session机制的开始,它有一定概率开启垃圾回收,因为session是存放在文件中,
      PHP自身的垃圾回收是无效的,SESSION的回收是要删文件的,这个概率是根据php.ini的配置决定的,
      但是有的系统是 session.gc_probability =0,这也就是说概率是0,而是通过cron脚本来实现垃圾回收。

              session.gc_probability =1
              session.gc_divisor =1000
              session.gc_maxlifetime =1440//过期时间 默认24分钟
              //概率是 session.gc_probability/session.gc_divisor 结果 1/1000, 
              //不建议设置过小,因为session的垃圾回收,是需要检查每个文件是否过期的。
              session.save_path =//好像不同的系统默认不一样,有一种设置是 "N;/path"
              //这是随机分级存储,这个样的话,垃圾回收将不起作用,需要自己写脚本

 

    B、 session会判断当前是否有$_COOKIE[session_name()];session_name()返回保存session_id的COOKIE键值,
      这个值可以从php.ini找到

              session.name = PHPSESSID //默认值PHPSESSID

    C、 如果不存在会生成一个session_id,然后把生成的session_id作为COOKIE的值传递到客户端.
      相当于执行了下面COOKIE 操作,注意的是,这一步执行了setcookie()操作,COOKIE是在header头中发送的,
      这之前是不能有输出的,PHP有另外一个函数 session_regenerate_id() 如果使用这个函数,这之前也是不能有输出的。

                setcookie(session_name(),
                          session_id(),
                          session.cookie_lifetime,//默认0
                          session.cookie_path,//默认'/'当前程序跟目录下都有效
                          session.cookie_domain,//默认为空
                          )

    D、 如果存在那么session_id =$_COOKIE[session_name];
      然后去session.save_path指定的文件夹里去找名字为'SESS_'.session_id()的文件.
      读取文件的内容反序列化,然后放到$_SESSION中

 2、 为$_SESSION赋值
    比如新添加一个值$_SESSION['test'] ='blah'; 那么这个$_SESSION只会维护在内存中,当脚本执行结束的时候,
    用把$_SESSION的值写入到session_id指定的文件夹中,然后关闭相关资源.      这个阶段有可能执行更改session_id的操作,
    比如销毁一个旧的的session_id,生成一个全新的session_id.一半用在自定义 session操作,角色的转换上,
    比如Drupal.Drupal的匿名用户有一个SESSION的,当它登录后需要换用新的session_id

          if (isset($_COOKIE[session_name()])) {
            setcookie(session_name(),'',time() -42000,'/');//旧session cookie过期
          }
          session_regenerate_id();//这一步会生成新的session_id
         //session_id()返回的是新的值

 3、 写入SESSION操作
    在脚本结束的时候会执行SESSION写入操作,把$_SESSION中值写入到session_id命名的文件中,可能已经存在,
    可能需要创建新的文件。

4、 销毁SESSION
    SESSION发出去的COOKIE一般属于即时COOKIE,保存在内存中,当浏览器关闭后,才会过期,假如需要人为强制过期,
    比如 退出登录,而不是关闭浏览器,那么就需要在代码里销毁SESSION,方法有很多,
            1. setcookie(session_name(),session_id(),time() -8000000,..);//退出登录前执行
            2. usset($_SESSION);//这会删除所有的$_SESSION数据,刷新后,有COOKIE传过来,但是没有数据。
            3. session_destroy();//这个作用更彻底,删除$_SESSION 删除session文件,和session_id

    当不关闭浏览器的情况下,再次刷新,2和3都会有COOKIE传过来,但是找不到数据




声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议