如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留链接信息。

cookie作为小甜饼,充斥着网络世界。没有了cookie,那么估计大多数的网站鉴权功能就全部失效了。可见cookie的重要性。今天苏南大叔,给大家带来的是phpcookie的一些小事情。

  • 本文中的实验对象,是纯正的php,不夹杂任何任何框架的php。所以,所有的写法都是原生的,请知晓。
  • cookie输出之前,请确保没有任何的页面输出。即使一个空白字符也不行。苏南大叔想起了php新手经典大坑:php文件保存为utf8的时候,必须是nobom的。哈哈哈。
  • 顺便带来一道新浪的php面试题:如果浏览器禁用了cookie,那么session还能使用吗?当然,本文里面没有这个答案,答案见苏南大叔未来的文章,https://newsn.net/tag/cookie/

setcookie函数

bool setcookie ( string $name [, string $value = "" [, int $expire = 0 [, string $path = "" [, string $domain = "" [, bool $secure = false [, bool $httponly = false ]]]]]] )

函数说明见这里:https://doc.php.sh/zh/function.setcookie.html

  • $name 不就必说了,cookie的项目名称,一般为个类似“str”的字符串,但是也数组的形式,例如“arr[one]”。
  • $value 传输的过程中会被转义,比如空格会变成加号等,其转义函数,据苏南大叔推断,应该是urlencode。
  • $expire 时间戳,秒数而非毫秒数,cookie的过期时间,是具体的时间点,而非时间段,PHP会对它做进一步的转换为GMT格式。。一般都是控制这个时间为一个过去的时间,来删除掉cookie的。不填或者填0的话,就是浏览器会话期间生效,浏览器关闭即失效。表示过期时间的时候,http协议里面有2个,expire和max-age。目前php里面还是设置expire过期时间的,但是从http协议的角度上看,expire已经开始被max-age取代。expire指的是失效的时间点,max-age是多少秒后失效。
  • $path cookie的有效目录,一般是和$domain配置使用的,一般设置为/即可。
  • $domain 这个参数需要重点注意,如果不填的话,则是默认当前域名。如果填写的话,一般来说,也是需要自己用 $_SERVER['SERVER_NAME']获得的域名。并且主动填写的话,最终的cookie作用域是填写的所有子域。如果填写"newsn.net",那么反应到浏览器端,最终的值是“.newsn.net"。注意,前面添加了个".",表示的范围就扩大了。
  • $secure 另外一个很邪门的参数,表示是否仅仅通过安全的 HTTPS 连接传给客户端。如果设置为true的话,当前网站环境不是https的话,那么这整个cookie就是完全失效的状态。但是,我们通过抓包可以发现,这个cookie已经被php设置,

只不过在浏览器端被失效了。而php中,是可以通过isset($_SERVER["HTTPS"])来判定,是否支持https的。

  • $httponly 这个参数的位置也非常尴尬,是所有可选参数的最后一个。想设置它,就必须先设置 $domain$secure 这两个似乎可以不必设置的值。而在目前的网络环境里面,$httponly 又应该是强烈推荐设置值。具体情况请参见苏南大叔的后续httponly文章。https://newsn.net/tag/httponly/

所以,很有可能你需要的php语句是这样的:

setcookie("cookie_name", "cookie_value", time() + 3600, "/", $_SERVER['SERVER_NAME'], isset($_SERVER["HTTPS"]), true);

setrawcookie函数

bool setrawcookie ( string $name [, string $value [, int $expire = 0 [, string $path [, string $domain [, bool $secure = false [, bool$ httponly = false ]]]]]] )

setrawcookiesetcookie,基本一致,区别就在于对$value的处理。下面的两条语句是一致的效果:

setcookie($name,$value);
setrawcookie($name,urlencode($value));

特别说明:

  • urlencoderawurlencode是有区别的,两者的区别不在本篇文章中叙述。需要明确的就是,两者是有区别的。
  • setrawcookie$value,不进行encode操作的话,如果里面含有空格的话,整条语句都是失效的。并且不会报错!所以,setrawcookie必须联合urlencode才能保证其正确性。但是这个时候,就不如使用setcookie了。

header输出cookie

set cookie函数,如果想要生效,也是通过header设置浏览器端进而生效的。所以通过header输出也是可行的。那么关于写出几条等价的header操作,大家对比学习一下:

header("Set-Cookie:cookie_name1_cp=" . urlencode("浏览器关闭失效"));
setcookie("cookie_name1", "浏览器关闭失效");

php设置cookie的三种方法比较 - 001

header("Set-Cookie:cookie_name=" . urlencode("设置有效域名/https/httponly") . "; expires=" . gmstrftime("%a, %d-%b-%Y %H:%M:%S GMT", time() + 3600*24) . "; Max-Age=3600; path=/; domain= ".$_SERVER['SERVER_NAME']."; httponly");
setcookie("cookie_name3", "设置有效域名/https/httponly", time() + 3600*24, "/", $_SERVER['SERVER_NAME'], isset($_SERVER["HTTPS"]),true);

php设置cookie的三种方法比较 - 002

需要注意的是:

  • 设置内容的时候,会对特殊字符进行转义。setcookie的转义是自动的,header的转义是主动的。
  • 使用header的时候,过期时间是个gmt时间字符串,而setcookie是个时间戳。
  • 设置域名的时候,两者都直接写的域名,但是生效的时候,生效的是.域名,就是说生效范围包括二级域名。
  • headersetcookie好的地方在于:它可以跳过哪些过期时间/域名/path等参数,直接设置httponly

最后对比

下面来个phpcookie相关函数的终极对决:

<?php
$val="我是中文 newsn.net";
setcookie("cookie_normal",$val);
setrawcookie("cookie_raw",urlencode($val));
setrawcookie("cookie_raw2",rawurlencode($val));
header("Set-Cookie:cookie_header=带 空 + 格 的中文",false);
?>
<script src="js/jquery-3.2.1.min.js"></script>
<script src="js/jquery.cookie.js"></script>
<script>
  var cookie_normal=$.cookie('cookie_normal');
  var cookie_raw=$.cookie('cookie_raw');
  var cookie_raw2=$.cookie('cookie_raw2');
  var cookie_header=$.cookie('cookie_header');
  document.write(document.cookie+"<br/><br/>normal:"+cookie_normal+",<br/>raw:"+cookie_raw+",<br/>raw2:"+cookie_raw2+",<br/>header:"+cookie_header);
</script>

php设置cookie的三种方法比较 - 010

这些cookie值使用了不同的方法进行了设置。里面含有空格和加号。从结果中,我们得出如下结论:

  • setcookiesetrawcookie中的中文,用document.cookie不能顺利读出,但是用jquery.cookie可以顺利读出。
  • jquerycookie插件,均正确读取了php端的各种cookie值。但是读取header中的值时,对加号的处理似乎有些问题。
  • document.cookie,只能正常读取header设置的中文。即使中文中带有空格,也能正常读取。这也是最正常,表现最好的组合。

总结

表面上看,使用header设置cookie和使用setcookie函数设置cookie,是可以得到相同的效果的。苏南大叔认为,用header设置cookie,比setcookie更好些。下一篇文章中将继续叙述相关事宜。敬请期待。

在实际操作中,还是有意料之外的事情的。想知道更多关于cookie的小秘密嘛?那么,请继续关注苏南大叔的cookie相关文章。

本站采用创作共用版权协议, 要求署名、非商业用途和相同方式共享。
转载本站内容必须也遵循“署名-非商业用途-相同方式共享”的创作共用协议。
程序如此灵动~》下所有原创文章,如被用于商业用途,请您按规定支付稿费。