博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
php入门第七天
阅读量:6812 次
发布时间:2019-06-26

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

    Form的提交及页面间的传值。

 

    Cookie是存放在客户的硬盘上的文件,每种浏览器都有它各自的位置。记得有一回我用不同的浏览器上两个百度号,结果两个浏览器上的用户都成了我后上的那个号,这个用浏览器的Cookie是做不到的,显然用的是flash cookie。也许是为了方便用多个号发贴的人,后来就没遇到这样的事了。Flash是个比较不安全的东西,但有时又不得不用,比如要在新浪上传相片,用没有Flash的浏览器来,虽然相应地显示了有file控件的界面,但图就是传不上去,不知道出于什么目的。吐完了,说正文。

 

<?php

session_start();

$_SESSION['list'] = [4, 3, 2, 1, '1', '"', "'", ['a' => 1, 'b' => 2]];

//序列化输出 session

echo serialize($_SESSION);

?>

然后,你在opera浏览器中的首选项查看cookie,点管理cookie,在本地的ip(一般是127.0.0.1)可以看到一个PHPSESSID,也就是说在一般情况下,session的key是基于客户的浏览器的。

 

如果你的wamp安装在D:\wamp,那么你可以在D:\wamp\tmp找到session文件,用记事本之类的软件打开,文件内容和序列化的session差不多。

 

Cookie和Session在同一浏览器的各个页面都是同样的值

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<?php

 

isset($_SESSION) === FALSE && print('没有$_SESSION这个数组,因为没session_start()');

session_start();

var_dump(['session' => $_SESSION], ['cookie' => $_COOKIE]);

 

/*Session 和 Cookie都是有时间限制的。但是cookie不支持数组,所以要存数组,需要先序列化,读数组时再反序列化。用json格式更短,但php的json要if很多情况,速度较慢,数组转过去,转回来的却是对象,反而不方便*/

$request_time = $_SERVER['REQUEST_TIME'];

setCookie('test_time', serialize([date('His', $request_time)]), $request_time+3600);

if (isset($_COOKIE['test_time']))

{// 删除cookie只需要先把值置为空,再让它时间到期就行。

    echo $_COOKIE['test_time'];

    setCookie('test_time', '', $request_time-3600);

}

?>

 

Session这样销毁

 

<?php

//第一步:开启Session并初使化

session_start();       

//第二步:还原Session

$_SESSION = array();   

//第三步:如果使用基于Cookie的Session,使用setCooike()删除包含Session Id的Cookie

$session_name = session_name();

isset($_COOKIE[$session_name]) && setcookie($session_name, '', time()-43200, '/');

 

//第四步:最后彻底销毁Session

session_destroy();

?>

    cookie的大小是受浏览器设置的限制的,一般浏览器都设为1000个字节长,一般够用;至于session则理论上只受服务器的硬盘大小的限制。但php自带的session有个问题,就是服务器的session的数量过多时,储存器的读写效率会很低下,所以一般较大的项目一般用sql或nosql来模似session的功能,而且这也直接解决了有多台服务器操作session的问题。

 

    Session的id是可以不用cookie的,一般是用url或隐藏域来代替,这种技术主要用于不支持cookie的比较老的手机的,一般这种手机在中国是没有的。url或隐藏域来作键是更安全的,这样就算客户的机子上有扫描用户cookie的软件,也是可以保护用户隐私的,因为他只存在于浏览器开着的时候,当然缓存文件是会记录有隐藏域的html的。但这个方法有三个缺点:

1、程序上不如用cookie做id来得方便。

2、跨界面性较差,比如你开了两个界面在同一浏览器,在一个界面上了,另一个没上,另一个的你点链接及在本页都不会让你上去。所以只适合手机这样的单页应用。

3、如果客户把浏览器关了,客户下次是无没自动登入的。

关于cookie的安全性:

    Cookie作为session的key时是用来确定用户的身份的,如果别人知道这个key就可以冒充用户,或者知道用户上了你的网站。

 

    又想说闲话了。话说MySpace这个网站,原来是美国的社交的主流的网站,这个网站很草根,什么英德裔、西班牙裔和非洲裔什么人都有。后来FaceBook创建了,它是基于常青藤大学的社交,所以美国社会的主流人群英德裔都跑那去了,MySpace就只有西班牙裔和非洲裔这样的少数民族了。

 

    所以你上了MySpace,结果你上别的网站,让别的网站读了你的cookie,向你推送针对西班牙裔和非洲裔的广告,不知道你会咋想。或者三K党在你家安了流氓软件,发现你就是那个在MySpace“说他们坏话”的人,先通过IP找到你家大概的位置(ivp4因为数量有限,所以并不是每家一个ip,而是你上线时,电信根据你的大概位置给你一个零时的IP;ivp6则可以做到一家一个ip,相当于网络实名制),正好你又是典型的美国式的单门独院,从你的电脑找你上了MySpace的证据,然后把你家人秘密枪决了之类的。

 

    一般网站还会在cookie中存一些不会影响到多个页面的逻辑的,而且他们认为不影响网站数据安全及客户个人隐私的一些东西。比如用cookie做购物车存些商品。

 

    关于cookie的安全性问题,只要你电脑没流氓软件,浏览器安全级别设置合理,不让javascript读取cookie等,一般不会有问题。

 

    你上一个网站,是因为你信任它,但它可能会不经过你同意而共享你的信息。比如你上新浪,会看到淘宝的广告,因为淘宝有新浪的股权,所以新浪可能会向淘宝共享你的信息,以便投放更准确的广告。另外新浪好像在美国上市的,所以会不会参加了美帝的梭镜计划也不好说。嗯,以上的话都没有事实根据,如有雷同,纯属巧合。

 

回正题:

    FORM默认的提交方法(method属性)是get,这种方法的一般是用于请求和查询数据的。get传送的信息会在地址栏显示,且方便缓存,虽然url长度有限制,但用于查询是足够了的,也防止有的人提交过多的信息。

    在form.method为post时,处理这个页面的地址(action属性)默认是$_REQUEST['REQUEST_URI'];form.method为get时,action中用get传的值也就是$_REQUEST['QUERY_STRING']会被清除,留下空间给get提交,相当于$_REQUEST['PHP_SELF']。所以对于不能用cookie的手机,当用户登入后,便用把get当cookie用,用户则用post提交和有$_REQUEST['QUERY_STRING']的链接来向服务器请求,这时查询就只能用post了。用下面的代码操作一下,就明白了。

    下面的用网址 test.php/abc/tre?test=123 进去,会发现$_SERVER 的值的不同

 

<!-- form_test.php start -->

<?php ?> 

 

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

<head>

<meta http-equiv="content-type" content="text/html; charset=UTF-8">

<meta name="generator" content="PSPad editor, www.pspad.com">

<title></title>

 

</head>

<body>

<form action="<?php if (isset($_REQUEST['action'])) {echo $_SERVER[$_REQUEST['action']];}; ?>" method="<?php if ( ! isset($_REQUEST['get'])): ?>post<?php endif; ?>" accept-charset="utf-8" > 

 

<br/>id <input type="text" name="id" id="id" value="" maxlength="100" size="50" style="width:50%" />

<br/>name[] <input type="text" name="name[]" id="name" value="" maxlength="100" size="50" style="width:50%" />

<br/>name[] <input type="text" name="name[]" id="name" value="" maxlength="100" size="50" style="width:50%" />

<br/>area[bei] <input type="text" name="name[bei]" value="" maxlength="100" size="50" style="width:50%" />

<br/>area[YII] <input type="text" name="name[YII]" value="" maxlength="100" size="50" style="width:50%" />

 

<br/>

<input type="checkbox" name="get" value="">用GET提交

<input type="radio" name="action" value="REQUEST_URI">REQUEST_URI

<input type="radio" name="action" value="SCRIPT_NAME">SCRIPT_NAME

<input type="radio" name="action" value="PHP_SELF">PHP_SELF

  

<br/><input type="submit" name="submit" value="Submit Post!" />

<br/><input type="submit" name="submit2" value="Submit2 Post!" />

<br/><input type="reset" id="reset" value="重置">

 

<br/>

<?php if (isset($_POST['submit'])): ?>

isset($_POST['submit'])

<?php elseif (isset($_POST['submit2'])): ?>

isset($_POST['submit2'])

<?php else: ?>

还没提交

<?php endif; ?>

<?php 

var_dump(['$_POST' => $_POST]

, ['$_GET' => $_GET]

, ['$_SERVER' => $_SERVER]); 

?>

</form>

 

<script>

 

document.getElementById('reset').onclick = function() {

return confirm("确定要复原")

};

 

</script>

</body>

</html>

<!-- form_test.php end -->

 

    get因为基于url,易于保存状态,并可以方便地在页面间传值。但要用post保存状态就麻烦一些。先让我们看看CI用的隐藏域传值。

if ( ! function_exists('form_hidden'))

{

    function form_hidden($name, $value = '', $recursing = FALSE)

    {

        static $form;

 

        if ($recursing === FALSE)

        {

            $form = "\n";

        }

 

        if (is_array($name))

        {

            foreach ($name as $key => $val)

            {

                form_hidden($key, $val, TRUE);

            }

            return $form;

        }

 

        if ( ! is_array($value))

        {

            $form .= '<input type="hidden" name="'.$name.'" value="'.form_prep($value, $name).'" />'."\n";

        }

        else

        {

            foreach ($value as $k => $v)

            {

                $k = (is_int($k)) ? '' : $k;

                form_hidden($name.'['.$k.']', $v, TRUE);

            }

        }

 

        return $form;

    }

}

 

if ( ! function_exists('form_prep'))

{

    function form_prep($str = '', $field_name = '')

    {

        static $prepped_fields = array();

 

        // if the field name is an array we do this recursively

        if (is_array($str))

        {

            foreach ($str as $key => $val)

            {

                $str[$key] = form_prep($val);

            }

 

            return $str;

        }

 

        if ($str === '')

        {

            return '';

        }

 

        // we've already prepped a field with this name

        // @todo need to figure out a way to namespace this so

        // that we know the *exact* field and not just one with

        // the same name

        if (isset($prepped_fields[$field_name]))

        {

            return $str;

        }

 

        $str = htmlspecialchars($str);

 

        // In case htmlspecialchars misses these.

        $str = str_replace(array("'", '"'), array("'", """), $str);

 

        if ($field_name != '')

        {

            $prepped_fields[$field_name] = $field_name;

        }

 

        return $str;

    }

}

 

CI的说明是这样说的, form_hidden()

可以使你创建一个隐藏输入栏。你可以输入name和value来创建一个:

form_hidden('username', 'johndoe');

// 将产生:
<input type="hidden" name="username" value="johndoe" />

或者你也可以使用数组来联合创建它们:

$data = array(

              'name'  => 'John Doe',
              'email' => 'john@example.com',
              'url'   => 'http://example.com'
            );
echo form_hidden($data);
// 将产生:
<input type="hidden" name="name" value="John Doe" />
<input type="hidden" name="email" value="john@example.com" />
<input type="hidden" name="url" value="http://example.com" />

 

    不过我觉得如果用textarea代替hidden,不就不用怕单双引号破坏表单了吗,要隐藏,只需要<div style="display:none"><textarea 。。。。。。。。 </div>就可以也吗, 接着form_prep那句改成htmlspecialchars就可以了。

 

    有时觉得麻烦,可以直接拷上个模版的代码,再用<div style="display:none"></div>一夹也可行,但不建议这样做。

 

    另外还可以用序列化加base64来做。下面的函数还可以用来传URL和表单,而不会破坏URL和表单。

 

if ( ! function_exists('form_url_encode'))

{

    function form_url_encode($input)

    {

        return strtr(

            base64_encode(

                serialize($input)

            ), '+/=', '-_,'

        );

    }

}

 

 

 

if ( ! function_exists('form_url_decode'))

{

    function form_url_decode($input)

    {

        return unserialize(

            base64_decode(

                strtr($input, '-_,', '+/=')

            )

        );

    }

}

 

效率很高,不过生成的字符串会有些长。而且读的时候要decode。

 

转载于:https://www.cnblogs.com/erlanp/p/3209459.html

你可能感兴趣的文章
Java 扫描包下所有类(包括jar包)
查看>>
VBS弹出来的对话框如何置顶!--果然技巧
查看>>
什么是Satoshi?和比特币中本聪有什么关系?
查看>>
iOS开发frame, contentSize, contentOffset, contentInset 区别联系浅析
查看>>
限流算法之漏桶算法、令牌桶算法
查看>>
排序算法 - 冒泡排序
查看>>
讨论一个堆栈越界的问题
查看>>
再次简单明了总结flex布局,一看就懂...
查看>>
dubbo源码解析(二十六)远程调用——http协议
查看>>
如何在账号之间迁移阿里云ECS
查看>>
# 每日两道前端面试题 #
查看>>
浅析webpack源码之前言(一)
查看>>
js设计模式--发布订阅模式
查看>>
手把手教你用koa+mongoodb实现自己的接口
查看>>
项目管理与需求变动的探讨
查看>>
未来你是CTO还是架构师?
查看>>
2018年11月TIOBE编程语言排行榜,Java稳居第一
查看>>
Nervos 与 AlphaWallet 正式建立深度合作关系
查看>>
JavaScript之关于this对象
查看>>
阿里云自助诊断系统技术解析
查看>>