整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

JavaScript浏览器端数据存储方案之Cooki

JavaScript浏览器端数据存储方案之Cookie篇

做项目的过程中,我们经常遇到需要把信息存储在本地的情况,比如权限验证的token、用户信息、埋点计数、客户配置的皮肤信息或语言种类等,我们可以暂存一下避免浏览器不必要的请求和客户多余操作,给客户使用带来方便。

那么浏览器存储有哪些方法呢,主要有:cookie、localStorage、sessionStorage、IndexedDB

Cookie

这个讲起来很简单,了解http的同学,肯定知道,http是一个不保存状态的协议,什么叫不保存状态,就是一个服务器是不清楚是不是同一个浏览器在访问他,在cookie之前,有另外的技术是可以解决,这里简单讲一下,就是在请求中插入一个token,然后在发送请求的时候,把这个东西带给服务器,这种方式是易出错,所以有了cookie的出现

cookie是什么,cookie就是一种浏览器管理状态的一个文件,它有name,也有value,后面那些看不见的是Domain、path等等,我们后面会介绍

cookie原理

第一次访问网站的时候,浏览器发出请求,服务器响应请求后,会将cookie放入到响应请求中,在浏览器第二次发请求的时候,会把cookie带过去,服务端会辨别用户身份,当然服务器也可以修改cookie内容

cookie不可跨域

javascript:document.cookie='myname=name1;path=/;domain=.baidu.com';
javascript:document.cookie='myname=name2;path=/;domain=.google.com';

当我将这两个语句都放到浏览器控制台运行的时候,你会发现一点,注意,上面两个cookie的值是不相同的,看清楚

显而易见的是,真正能把cookie设置上去的只有domain是.baidu.com的cookie绑定到了域名上,所以上面所说的不可跨域性,就是不能在不同的域名下用,每个cookie都会绑定单一的域名

cookie的属性

cookie的属性众多,我们可以来看一下下面这张图,然后我们一个一个分析

name

这个显而易见,就是代表cookie的名字的意思,一个域名下绑定的cookie,name不能相同,相同的name的值会被覆盖掉,有兴趣的同学可以试一试,我在项目中切实用到过

value

这个就是每个cookie拥有的一个属性,它表示cookie的值,但是我在这里想说的不是这个,因为我在网上看到两种说法,如下:

  • cookie的值必须被URL编码
  • 对cookie的值进行编码不是必须的,还举了原始文档中所说的,仅对三种符号必须进行编码:分号、逗号和空格

我在网上看到那么一种说法:

由于cookie规定是名称/值是不允许包含分号,逗号,空格的,所以为了不给用户到来麻烦,考虑服务器的兼容性,任何存储cookie的数据都应该被编码。

domain

这个是指的域名,这个代表的是,cookie绑定的域名,如果没有设置,就会自动绑定到执行语句的当前域,还有值得注意的点,统一个域名下的二级域名也是不可以交换使用cookie的,比如,你设置www.baidu.com和image.baidu.com,依旧是不能公用的

path

path这个属性默认是'/',这个值匹配的是web的路由,举个例子:

//默认路径
www.baidu.com
//blog路径
www.baidu.com/blog复制代码

我为什么说的是匹配呢,就是当你路径设置成/blog的时候,其实它会给/blog、/blogabc等等的绑定cookie

cookie的有效期

什么是有效期,就是图中的Expires属性,一般浏览器的cookie都是默认储存的,当关闭浏览器结束这个会话的时候,这个cookie也就会被删除,这就是上图中的——session(会话储存)。

如果你想要cookie存在一段时间,那么你可以通过设置Expires属性为未来的一个时间节点,Expires这个是代表当前时间的,这个属性已经逐渐被我们下面这个主人公所取代——Max-Age

Max-Age,是以秒为单位的,Max-Age为正数时,cookie会在Max-Age秒之后,被删除,当Max-Age为负数时,表示的是临时储存,不会生出cookie文件,只会存在浏览器内存中,且只会在打开的浏览器窗口或者子窗口有效,一旦浏览器关闭,cookie就会消失,当Max-Age为0时,又会发生什么呢,删除cookie,因为cookie机制本身没有设置删除cookie,失效的cookie会被浏览器自动从内存中删除,所以,它实现的就是让cookie失效。

secure

这个属性译为安全,http不仅是无状态的,还是不安全的协议,容易被劫持,打个比方,你在手机端浏览网页的时候,有没有中国移动图标跳出来过,闲言少叙,当这个属性设置为true时,此cookie只会在https和ssl等安全协议下传输

  • 提示:这个属性并不能对客户端的cookie进行加密,不能保证绝对的安全性

HttpOnly

这个属性是面试的时候常考的,如果这个属性设置为true,就不能通过js脚本来获取cookie的值,能有效的防止xss攻击,看MDN的官方文档:

关于js操作cookie

document.cookie可以对cookie进行读写,看一下两条指令

//读取浏览器中的cookie
console.log(document.cookie);
//写入cookie
document.cookie='myname=laihuamin;path=/;domain=.baidu.com';

一般在项目中使用我们都会选择将其封装成一个工具函数

不过现在有一些第三方的库做的更好、更安全,我们完全可以拿来即用,例如Js-Cookie

用法超级和谐

$ npm install js-cookie --save

Create a cookie, valid across the entire site:

Cookies.set('name', 'value');

Create a cookie that expires 7 days from now, valid across the entire site:

Cookies.set('name', 'value', { expires: 7 });

Create an expiring cookie, valid to the path of the current page:

Cookies.set('name', 'value', { expires: 7, path: '' });

Read cookie:

Cookies.get('name'); //=> 'value'
Cookies.get('nothing'); //=> undefined

Read all visible cookies:

Cookies.get(); //=> { name: 'value' }

Delete cookie:

Cookies.remove('name');

Delete a cookie valid to the path of the current page:

Cookies.set('name', 'value', { path: '' });
Cookies.remove('name'); // fail!
Cookies.remove('name', { path: '' }); // removed!

IMPORTANT! When deleting a cookie and you're not relying on the default attributes, you must pass the exact same path and domain attributes that were used to set the cookie:

Cookies.remove('name', { path: '', domain: '.yourdomain.com' });

服务端如何去设置cookie

关于怎么设置cookie,我们只要打开控制台,看一个http的请求头和响应头中的东西即可明白

服务端就是通过setCookie来设置cookie的,注意点,要设置多个cookie时,得多写几个setCookie,我们还可以从上图看到,请求可以携带cookie给后端

HTML标签相关的字符串格式化

string nl2br ( string $string )

nl2br() 就是将\n 替换成 <br> //javascript对\n才能够执行换行,对</br>是不能执行换行

htmlspecialchars() 把一些预定义的字符转换为 HTML 实体。

string htmlspecialchars(string,quotestyle,[character-set])

转换以下字符及对应的实体

& (和号) 成为 &
" (双引号) 成为 "
' (单引号) 成为 '
< (小于) 成为 <
> (大于) 成为 >

第二个参数: ENT_COMPAT 只转换双引号, 保留单引号, 为默认值 compat: 兼容性

ENT_QUOTES 同时转换两种引号 quotes: 引号

ENT_NOQUOTES 不对引号进行转换

<html>
<body>
<?php
$str="John & \" 'Adams'";
echo htmlspecialchars($str, ENT_COMPAT);
echo "<br />";
echo htmlspecialchars($str, ENT_QUOTES);
echo "<br />";
echo htmlspecialchars($str, ENT_NOQUOTES);
?>
</body>
</html>

输出结果:John & " 'Adams'

John & " 'Adams'

John & " 'Adams'

htmlentities() 可以将所有的非ASCII码字符转换为对应的实体代码;除字母、数字、\外, 汉字和键盘上其他字符都转换

<?php
$str="A 'quote' \" is <b>bold</b>" ;
echo htmlentities ( $str ); // 输出后源代码: A 'quote' is <b>bold</b>
echo htmlentities ( $str , ENT_QUOTES ); // 输出后源代码: A 'quote' is <b>bold</b>
?>

返回的结果:A 'quote' "is <b>bold</b>

A 'quote' "is <b>bold</b>

注意: htmlspecialchars()和htmlentities作用直接输出HTML脚本

htmlspecialchars()和htmlentities()函数对于转义字符"\"处理,不会转义实体代码,要么当转义字符对待,要么原样输出;

PHP中htmlentities和htmlspecialchars的区别

这两个函数的功能都是转换字符为HTML字符编码, 特别是url和代码字符串。防止字符标记被浏览器执行。

使用中文时没什么区别, 但htmlentities会格式化中文字符使得中文输入是乱码。

htmlentities转换所有的html标记, htmlspecialchars只格式化& ' " < 和 > 这几个特殊符号

addslashes() 在指定的预定义字符前添加反斜杠。

这些预定义字符是:单引号 (') 双引号 (") 反斜杠 (\) NULL字符(\x00)

提示:该函数可用于为存储在数据库中的字符串以及数据库查询语句准备合适的字符串。

注释:默认情况下,PHP 指令 magic_quotes_gpc 为 on,对所有的 GET、POST 和 COOKIE数据自动运行 addslashes()。

不要对已经被magic_quotes_gpc转义过的字符串使用 addslashes(),因为这样会导致双层转义。

遇到这种情况时可以使用函数 get_magic_quotes_gpc() 进行检测。(如:$c=(!get_magic_quotes_gpc())?addslashes($c):$c;)

在本例中,我们要向字符串中的预定义字符添加反斜杠:

<?php
$str="Who's John Adams?";
echo $str . " This is not safe in a database query.<br />";
echo addslashes($str) . " This is safe in a database query.";
?>

输出:

Who's John Adams? This is not safe in a database query.

Who\'s John Adams? This is safe in a database query.

<?php
header("Content-type:text/html; charset=utf-8");
$str="wo are \x0a studying \x00 php";
echo $str;
echo "<br>";
echo addslashes($str);
?>

输出:

wo are studying php

wo are studying >wo are studying \0 php< php



stripslashes() 删除反斜线("\")

在提交的表单数据中 ' " \ 等字符前被自动加上一个\ ,这是配置文件php.ini中选项magic_quotes_gpc在起作用,

默认是打开的,如果不处理则将数据保存到数据库时,有可能会被数据库误当成控制符号而引起错误。

通常htmlspecialchars()和stripslashes()函数复合的方式,联合处理表单中的提交的数据htmlspecialchars(stripslashes())

strip_tags()

string strip_tags ( string $str [, string $allowable_tags ] )

剥去 HTML、XML 以及 PHP 的标签。

<?php
echo strip_tags("Hello <b><i>world!</i></b>","<b>");
?>

输出结果:Hello world!

实例:

<?php
$str="<b>webserver;</b> & \ 'Linux' & Apache";
echo "$str"; //直接输出
echo "<br/>";
echo htmlspecialchars($str,ENT_COMPAT); //只转换双引号,为默认参数
echo "<br />";
echo htmlspecialchars($str,ENT_NOQUOTES); //不对引号进行转换
echo "<br />";
echo htmlspecialchars($str,ENT_QUOTES); //同时转换单引号和双引号
echo "<br />";
echo htmlentities($str); //将所有的非ASCII码字符转换为对应的实体代码
echo "<br />";
echo addslashes($str); //将" ' \ 字符前添加反斜线
echo "<br />";
echo stripslashes($str); //删除反斜线
echo "<br />";
echo strip_tags($str); //删除<html>标记
?>

输出结果:

webserver; & \ 'Linux' & Apache

么是cookie?

cookie用于存储web页面的用户信息。
Cookie 是一些数据, 存储于你电脑上的文本文件中。
当 web 服务器向浏览器发送 web 页面时,在连接关闭后,服务端不会记录用户的信息。
Cookie 的作用就是用于解决 "如何记录客户端的用户信息":
当用户访问 web 页面时,他的名字可以记录在 cookie 中。
在用户下一次访问该页面时,可以在 cookie 中读取用户访问记录。

创建cookie

javascript可以使用document.cookie属性来创建、读取、及删除cookie。

//可以为cookie添加一个过期时间,默认情况下,cookie在浏览器关闭时删除
document.cookie="username=John Doe; expires=Thu, 18 Dec 2043 12:00:00 GMT; path=/";

读取cookie

var x=document.cookie;
	document.cookie 将以字符串的方式返回所有的 cookie,
  类型格式: cookie1=value; cookie2=value; cookie3=value;

删除cookie